Enable overlays on background thread.
Change-Id: I445022c2f05788f89a7dd412f70229b4874ebda3 Fixes: 112741125 Test: m RunSettingsRoboTests
This commit is contained in:
@@ -9557,6 +9557,8 @@
|
|||||||
|
|
||||||
<!-- [CHAR_LIMIT=NONE] Developer Settings: Label for the option that turns off all overlays in a given category. -->
|
<!-- [CHAR_LIMIT=NONE] Developer Settings: Label for the option that turns off all overlays in a given category. -->
|
||||||
<string name="overlay_option_device_default">Device default</string>
|
<string name="overlay_option_device_default">Device default</string>
|
||||||
|
<!-- [CHAR_LIMIT=NONE] Developer Settings: Toast displayed to the user when an overlay fails to apply. -->
|
||||||
|
<string name="overlay_toast_failed_to_apply">Failed to apply overlay</string>
|
||||||
|
|
||||||
<!-- [CHAR_LIMIT=60] Label for special access screen -->
|
<!-- [CHAR_LIMIT=60] Label for special access screen -->
|
||||||
<string name="special_access">Special app access</string>
|
<string name="special_access">Special app access</string>
|
||||||
|
@@ -22,9 +22,12 @@ import android.content.Context;
|
|||||||
import android.content.om.IOverlayManager;
|
import android.content.om.IOverlayManager;
|
||||||
import android.content.om.OverlayInfo;
|
import android.content.om.OverlayInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.preference.ListPreference;
|
import androidx.preference.ListPreference;
|
||||||
@@ -38,6 +41,7 @@ import com.android.settingslib.development.DeveloperOptionsPreferenceController;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preference controller to allow users to choose an overlay from a list for a given category.
|
* Preference controller to allow users to choose an overlay from a list for a given category.
|
||||||
@@ -46,6 +50,7 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class OverlayCategoryPreferenceController extends DeveloperOptionsPreferenceController
|
public class OverlayCategoryPreferenceController extends DeveloperOptionsPreferenceController
|
||||||
implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
|
implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
|
||||||
|
private static final String TAG = "OverlayCategoryPC";
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final String PACKAGE_DEVICE_DEFAULT = "package_device_default";
|
static final String PACKAGE_DEVICE_DEFAULT = "package_device_default";
|
||||||
private static final String OVERLAY_TARGET_PACKAGE = "android";
|
private static final String OVERLAY_TARGET_PACKAGE = "android";
|
||||||
@@ -100,12 +105,11 @@ public class OverlayCategoryPreferenceController extends DeveloperOptionsPrefere
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean setOverlay(String packageName) {
|
private boolean setOverlay(String packageName) {
|
||||||
String currentPackageName = null;
|
final String currentPackageName = getOverlayInfos().stream()
|
||||||
for (OverlayInfo o : getOverlayInfos()) {
|
.filter(info -> info.isEnabled())
|
||||||
if (o.isEnabled()) {
|
.map(info -> info.packageName)
|
||||||
currentPackageName = o.packageName;
|
.findFirst()
|
||||||
}
|
.orElse(null);
|
||||||
}
|
|
||||||
|
|
||||||
if (PACKAGE_DEVICE_DEFAULT.equals(packageName) && TextUtils.isEmpty(currentPackageName)
|
if (PACKAGE_DEVICE_DEFAULT.equals(packageName) && TextUtils.isEmpty(currentPackageName)
|
||||||
|| TextUtils.equals(packageName, currentPackageName)) {
|
|| TextUtils.equals(packageName, currentPackageName)) {
|
||||||
@@ -113,18 +117,33 @@ public class OverlayCategoryPreferenceController extends DeveloperOptionsPrefere
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean result;
|
new AsyncTask<Void, Void, Boolean>() {
|
||||||
|
@Override
|
||||||
|
protected Boolean doInBackground(Void... params) {
|
||||||
try {
|
try {
|
||||||
if (PACKAGE_DEVICE_DEFAULT.equals(packageName)) {
|
if (PACKAGE_DEVICE_DEFAULT.equals(packageName)) {
|
||||||
result = mOverlayManager.setEnabled(currentPackageName, false, USER_SYSTEM);
|
return mOverlayManager.setEnabled(currentPackageName, false, USER_SYSTEM);
|
||||||
} else {
|
} else {
|
||||||
result = mOverlayManager.setEnabledExclusiveInCategory(packageName, USER_SYSTEM);
|
return mOverlayManager.setEnabledExclusiveInCategory(packageName, USER_SYSTEM);
|
||||||
}
|
}
|
||||||
} catch (RemoteException re) {
|
} catch (RemoteException re) {
|
||||||
throw re.rethrowFromSystemServer();
|
Log.w(TAG, "Error enabling overlay.", re);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Boolean success) {
|
||||||
updateState(mPreference);
|
updateState(mPreference);
|
||||||
return result;
|
if (!success) {
|
||||||
|
Toast.makeText(
|
||||||
|
mContext, R.string.overlay_toast_failed_to_apply, Toast.LENGTH_LONG)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
|
||||||
|
return true; // Assume success; toast on failure.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -31,6 +31,8 @@ import android.content.om.OverlayInfo;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -38,6 +40,8 @@ import org.mockito.Mock;
|
|||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
import org.robolectric.RuntimeEnvironment;
|
import org.robolectric.RuntimeEnvironment;
|
||||||
|
import org.robolectric.shadows.ShadowApplication;
|
||||||
|
import org.robolectric.shadows.ShadowToast;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -105,21 +109,64 @@ public class OverlayCategoryPreferenceControllerTest {
|
|||||||
mockCurrentOverlays(ONE_DISABLED, TWO_DISABLED);
|
mockCurrentOverlays(ONE_DISABLED, TWO_DISABLED);
|
||||||
|
|
||||||
mController.onPreferenceChange(null, TWO_DISABLED.packageName);
|
mController.onPreferenceChange(null, TWO_DISABLED.packageName);
|
||||||
|
ShadowApplication.runBackgroundTasks();
|
||||||
|
|
||||||
verify(mOverlayManager)
|
verify(mOverlayManager)
|
||||||
.setEnabledExclusiveInCategory(eq(TWO_DISABLED.packageName), anyInt());
|
.setEnabledExclusiveInCategory(eq(TWO_DISABLED.packageName), anyInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onPreferenceChange_enable_fails() throws Exception {
|
||||||
|
mockCurrentOverlays(ONE_DISABLED, TWO_DISABLED);
|
||||||
|
when(mOverlayManager.setEnabledExclusiveInCategory(eq(TWO_DISABLED.packageName), anyInt()))
|
||||||
|
.thenReturn(false);
|
||||||
|
|
||||||
|
mController.onPreferenceChange(null, TWO_DISABLED.packageName);
|
||||||
|
ShadowApplication.runBackgroundTasks();
|
||||||
|
|
||||||
|
assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
|
||||||
|
RuntimeEnvironment.application.getString(R.string.overlay_toast_failed_to_apply));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onPreferenceChange_disable() throws Exception {
|
public void onPreferenceChange_disable() throws Exception {
|
||||||
mockCurrentOverlays(ONE_DISABLED, TWO_ENABLED);
|
mockCurrentOverlays(ONE_DISABLED, TWO_ENABLED);
|
||||||
|
|
||||||
mController.onPreferenceChange(
|
mController.onPreferenceChange(
|
||||||
null, OverlayCategoryPreferenceController.PACKAGE_DEVICE_DEFAULT);
|
null, OverlayCategoryPreferenceController.PACKAGE_DEVICE_DEFAULT);
|
||||||
|
ShadowApplication.runBackgroundTasks();
|
||||||
|
|
||||||
verify(mOverlayManager).setEnabled(eq(TWO_ENABLED.packageName), eq(false), anyInt());
|
verify(mOverlayManager).setEnabled(eq(TWO_ENABLED.packageName), eq(false), anyInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onPreferenceChange_disable_fails() throws Exception {
|
||||||
|
mockCurrentOverlays(ONE_DISABLED, TWO_ENABLED);
|
||||||
|
when(mOverlayManager.setEnabled(eq(TWO_ENABLED.packageName), eq(false), anyInt()))
|
||||||
|
.thenReturn(false);
|
||||||
|
|
||||||
|
mController.onPreferenceChange(
|
||||||
|
null, OverlayCategoryPreferenceController.PACKAGE_DEVICE_DEFAULT);
|
||||||
|
ShadowApplication.runBackgroundTasks();
|
||||||
|
|
||||||
|
assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
|
||||||
|
RuntimeEnvironment.application.getString(R.string.overlay_toast_failed_to_apply));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onPreferenceChange_disable_throws() throws Exception {
|
||||||
|
mockCurrentOverlays(ONE_DISABLED, TWO_ENABLED);
|
||||||
|
when(mOverlayManager.setEnabled(eq(TWO_ENABLED.packageName), eq(false), anyInt()))
|
||||||
|
.thenThrow(new RemoteException());
|
||||||
|
|
||||||
|
mController.onPreferenceChange(
|
||||||
|
null, OverlayCategoryPreferenceController.PACKAGE_DEVICE_DEFAULT);
|
||||||
|
ShadowApplication.runBackgroundTasks();
|
||||||
|
|
||||||
|
assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
|
||||||
|
RuntimeEnvironment.application.getString(R.string.overlay_toast_failed_to_apply));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void updateState_enabled() {
|
public void updateState_enabled() {
|
||||||
mockCurrentOverlays(ONE_DISABLED, TWO_ENABLED);
|
mockCurrentOverlays(ONE_DISABLED, TWO_ENABLED);
|
||||||
|
Reference in New Issue
Block a user