Merge "Disable activity process config override for certain display-based services." into rvc-dev am: 3b145e0b19
Change-Id: I51f9b25e72631a5a9db7405410e0ad89c3b8832d
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 21760cd..419389f 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -119,7 +119,6 @@
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Comparator;
-import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
@@ -1753,8 +1752,8 @@
private void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
boolean anyForeground = false;
int fgServiceTypes = 0;
- for (int i = proc.services.size() - 1; i >= 0; i--) {
- ServiceRecord sr = proc.services.valueAt(i);
+ for (int i = proc.numberOfRunningServices() - 1; i >= 0; i--) {
+ ServiceRecord sr = proc.getRunningServiceAt(i);
if (sr.isForeground || sr.fgRequired) {
anyForeground = true;
fgServiceTypes |= sr.foregroundServiceType;
@@ -1765,8 +1764,8 @@
private void updateWhitelistManagerLocked(ProcessRecord proc) {
proc.whitelistManager = false;
- for (int i=proc.services.size()-1; i>=0; i--) {
- ServiceRecord sr = proc.services.valueAt(i);
+ for (int i = proc.numberOfRunningServices() - 1; i >= 0; i--) {
+ ServiceRecord sr = proc.getRunningServiceAt(i);
if (sr.whitelistManager) {
proc.whitelistManager = true;
break;
@@ -1802,8 +1801,8 @@
}
boolean anyClientActivities = false;
- for (int i=proc.services.size()-1; i>=0 && !anyClientActivities; i--) {
- ServiceRecord sr = proc.services.valueAt(i);
+ for (int i = proc.numberOfRunningServices() - 1; i >= 0 && !anyClientActivities; i--) {
+ ServiceRecord sr = proc.getRunningServiceAt(i);
ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = sr.getConnections();
for (int conni = connections.size() - 1; conni >= 0 && !anyClientActivities; conni--) {
ArrayList<ConnectionRecord> clist = connections.valueAt(conni);
@@ -2995,7 +2994,7 @@
r.setProcess(app);
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
- final boolean newService = app.services.add(r);
+ final boolean newService = app.startService(r);
bumpServiceExecutingLocked(r, execInFg, "create");
mAm.updateLruProcessLocked(app, false, null);
updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
@@ -3036,7 +3035,7 @@
// Cleanup.
if (newService) {
- app.services.remove(r);
+ app.stopService(r);
r.setProcess(null);
}
@@ -3362,7 +3361,7 @@
synchronized (r.stats.getBatteryStats()) {
r.stats.stopLaunchedLocked();
}
- r.app.services.remove(r);
+ r.app.stopService(r);
r.app.updateBoundClientUids();
if (r.whitelistManager) {
updateWhitelistManagerLocked(r.app);
@@ -3652,7 +3651,7 @@
}
if (finishing) {
if (r.app != null && !r.app.isPersistent()) {
- r.app.services.remove(r);
+ r.app.stopService(r);
r.app.updateBoundClientUids();
if (r.whitelistManager) {
updateWhitelistManagerLocked(r.app);
@@ -3748,7 +3747,7 @@
didSomething = true;
Slog.i(TAG, " Force stopping service " + service);
if (service.app != null && !service.app.isPersistent()) {
- service.app.services.remove(service);
+ service.app.stopService(service);
service.app.updateBoundClientUids();
if (service.whitelistManager) {
updateWhitelistManagerLocked(service.app);
@@ -3861,24 +3860,22 @@
if (false) {
// XXX we are letting the client link to the service for
// death notifications.
- if (app.services.size() > 0) {
- Iterator<ServiceRecord> it = app.services.iterator();
- while (it.hasNext()) {
- ServiceRecord r = it.next();
- ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
- for (int conni=connections.size()-1; conni>=0; conni--) {
- ArrayList<ConnectionRecord> cl = connections.valueAt(conni);
- for (int i=0; i<cl.size(); i++) {
- ConnectionRecord c = cl.get(i);
- if (c.binding.client != app) {
- try {
- //c.conn.connected(r.className, null);
- } catch (Exception e) {
- // todo: this should be asynchronous!
- Slog.w(TAG, "Exception thrown disconnected servce "
- + r.shortInstanceName
- + " from app " + app.processName, e);
- }
+ int numberOfRunningServices = app.numberOfRunningServices();
+ for (int sIndex = 0; sIndex < numberOfRunningServices; sIndex++) {
+ ServiceRecord r = app.getRunningServiceAt(sIndex);
+ ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
+ for (int conni = connections.size() - 1; conni >= 0; conni--) {
+ ArrayList<ConnectionRecord> cl = connections.valueAt(conni);
+ for (int i = 0; i < cl.size(); i++) {
+ ConnectionRecord c = cl.get(i);
+ if (c.binding.client != app) {
+ try {
+ //c.conn.connected(r.className, null);
+ } catch (Exception e) {
+ // todo: this should be asynchronous!
+ Slog.w(TAG, "Exception thrown disconnected servce "
+ + r.shortInstanceName
+ + " from app " + app.processName, e);
}
}
}
@@ -3897,13 +3894,13 @@
app.whitelistManager = false;
// Clear app state from services.
- for (int i = app.services.size() - 1; i >= 0; i--) {
- ServiceRecord sr = app.services.valueAt(i);
+ for (int i = app.numberOfRunningServices() - 1; i >= 0; i--) {
+ ServiceRecord sr = app.getRunningServiceAt(i);
synchronized (sr.stats.getBatteryStats()) {
sr.stats.stopLaunchedLocked();
}
if (sr.app != app && sr.app != null && !sr.app.isPersistent()) {
- sr.app.services.remove(sr);
+ sr.app.stopService(sr);
sr.app.updateBoundClientUids();
}
sr.setProcess(null);
@@ -3962,13 +3959,13 @@
ServiceMap smap = getServiceMapLocked(app.userId);
// Now do remaining service cleanup.
- for (int i=app.services.size()-1; i>=0; i--) {
- ServiceRecord sr = app.services.valueAt(i);
+ for (int i = app.numberOfRunningServices() - 1; i >= 0; i--) {
+ ServiceRecord sr = app.getRunningServiceAt(i);
// Unless the process is persistent, this process record is going away,
// so make sure the service is cleaned out of it.
if (!app.isPersistent()) {
- app.services.removeAt(i);
+ app.stopService(sr);
app.updateBoundClientUids();
}
@@ -4018,7 +4015,7 @@
}
if (!allowRestart) {
- app.services.clear();
+ app.stopAllServices();
app.clearBoundClientUids();
// Make sure there are no more restarting services for this process.
@@ -4920,8 +4917,8 @@
if (pr.uid != uid) {
continue;
}
- for (int j = pr.services.size() - 1; j >= 0; j--) {
- ServiceRecord r = pr.services.valueAt(j);
+ for (int j = pr.numberOfRunningServices() - 1; j >= 0; j--) {
+ ServiceRecord r = pr.getRunningServiceAt(j);
if (!r.isForeground) {
continue;
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3fdf541..9b2743c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -18172,7 +18172,7 @@
for (int i = mProcessList.mRemovedProcesses.size() - 1; i >= 0; i--) {
final ProcessRecord app = mProcessList.mRemovedProcesses.get(i);
if (!app.hasActivitiesOrRecentTasks()
- && app.curReceivers.isEmpty() && app.services.size() == 0) {
+ && app.curReceivers.isEmpty() && app.numberOfRunningServices() == 0) {
Slog.i(
TAG, "Exiting empty application process "
+ app.toShortString() + " ("
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index b1fc029..50d2cab 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -702,10 +702,10 @@
}
// Bump up the crash count of any services currently running in the proc.
- for (int i = app.services.size() - 1; i >= 0; i--) {
+ for (int i = app.numberOfRunningServices() - 1; i >= 0; i--) {
// Any services running in the application need to be placed
// back in the pending list.
- ServiceRecord sr = app.services.valueAt(i);
+ ServiceRecord sr = app.getRunningServiceAt(i);
// If the service was restarted a while ago, then reset crash count, else increment it.
if (now > sr.restartTime + ProcessList.MIN_CRASH_INTERVAL) {
sr.crashCount = 1;
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 2d6ef81..ad85853 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -837,7 +837,8 @@
break;
}
- if (app.isolated && app.services.size() <= 0 && app.isolatedEntryPoint == null) {
+ if (app.isolated && app.numberOfRunningServices() <= 0
+ && app.isolatedEntryPoint == null) {
// If this is an isolated process, there are no services
// running in it, and it's not a special process with a
// custom entry point, then the process is no longer
@@ -1446,12 +1447,12 @@
}
int capabilityFromFGS = 0; // capability from foreground service.
- for (int is = app.services.size() - 1;
+ for (int is = app.numberOfRunningServices() - 1;
is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > PROCESS_STATE_TOP);
is--) {
- ServiceRecord s = app.services.valueAt(is);
+ ServiceRecord s = app.getRunningServiceAt(is);
if (s.startRequested) {
app.hasStartedServices = true;
if (procState > PROCESS_STATE_SERVICE) {
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 61ebc36..a1ec07c 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -261,9 +261,9 @@
// Controller for error dialogs
private final ErrorDialogController mDialogController = new ErrorDialogController();
// Controller for driving the process state on the window manager side.
- final private WindowProcessController mWindowProcessController;
+ private final WindowProcessController mWindowProcessController;
// all ServiceRecord running in this process
- final ArraySet<ServiceRecord> services = new ArraySet<>();
+ private final ArraySet<ServiceRecord> mServices = new ArraySet<>();
// services that are currently executing code (need to remain foreground).
final ArraySet<ServiceRecord> executingServices = new ArraySet<>();
// All ConnectionRecord this process holds
@@ -577,10 +577,10 @@
pw.println(Arrays.toString(isolatedEntryPointArgs));
}
mWindowProcessController.dump(pw, prefix);
- if (services.size() > 0) {
+ if (mServices.size() > 0) {
pw.print(prefix); pw.println("Services:");
- for (int i=0; i<services.size(); i++) {
- pw.print(prefix); pw.print(" - "); pw.println(services.valueAt(i));
+ for (int i = 0; i < mServices.size(); i++) {
+ pw.print(prefix); pw.print(" - "); pw.println(mServices.valueAt(i));
}
}
if (executingServices.size() > 0) {
@@ -735,6 +735,60 @@
}
}
+ /**
+ * Records a service as running in the process. Note that this method does not actually start
+ * the service, but records the service as started for bookkeeping.
+ *
+ * @return true if the service was added, false otherwise.
+ */
+ boolean startService(ServiceRecord record) {
+ if (record == null) {
+ return false;
+ }
+ boolean added = mServices.add(record);
+ if (added && record.serviceInfo != null) {
+ mWindowProcessController.onServiceStarted(record.serviceInfo);
+ }
+ return added;
+ }
+
+ /**
+ * Records a service as stopped. Note that like {@link #startService(ServiceRecord)} this method
+ * does not actually stop the service, but records the service as stopped for bookkeeping.
+ *
+ * @return true if the service was removed, false otherwise.
+ */
+ boolean stopService(ServiceRecord record) {
+ return mServices.remove(record);
+ }
+
+ /**
+ * The same as calling {@link #stopService(ServiceRecord)} on all current running services.
+ */
+ void stopAllServices() {
+ mServices.clear();
+ }
+
+ /**
+ * Returns the number of services added with {@link #startService(ServiceRecord)} and not yet
+ * removed by a call to {@link #stopService(ServiceRecord)} or {@link #stopAllServices()}.
+ *
+ * @see #startService(ServiceRecord)
+ * @see #stopService(ServiceRecord)
+ */
+ int numberOfRunningServices() {
+ return mServices.size();
+ }
+
+ /**
+ * Returns the service at the specified {@code index}.
+ *
+ * @see #numberOfRunningServices()
+ */
+ ServiceRecord getRunningServiceAt(int index) {
+ return mServices.valueAt(index);
+ }
+
void setCached(boolean cached) {
if (mCached != cached) {
mCached = cached;
@@ -768,9 +822,9 @@
return true;
}
- final int servicesSize = services.size();
+ final int servicesSize = mServices.size();
for (int i = 0; i < servicesSize; i++) {
- ServiceRecord r = services.valueAt(i);
+ ServiceRecord r = mServices.valueAt(i);
if (r.isForeground) {
return true;
}
@@ -1289,16 +1343,16 @@
}
void updateBoundClientUids() {
- if (services.isEmpty()) {
+ if (mServices.isEmpty()) {
clearBoundClientUids();
return;
}
// grab a set of clientUids of all connections of all services
ArraySet<Integer> boundClientUids = new ArraySet<>();
- final int K = services.size();
- for (int j = 0; j < K; j++) {
+ final int serviceCount = mServices.size();
+ for (int j = 0; j < serviceCount; j++) {
ArrayMap<IBinder, ArrayList<ConnectionRecord>> conns =
- services.valueAt(j).getConnections();
+ mServices.valueAt(j).getConnections();
final int N = conns.size();
for (int conni = 0; conni < N; conni++) {
ArrayList<ConnectionRecord> c = conns.valueAt(conni);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 93a7574..02f6a69 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -6604,7 +6604,6 @@
}
return;
}
- process.mIsImeProcess = true;
process.registerDisplayConfigurationListener(displayContent);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 194ed3e..41bd707 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -40,6 +40,7 @@
import static com.android.server.wm.ActivityTaskManagerService.KEY_DISPATCHING_TIMEOUT_MS;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityThread;
@@ -50,6 +51,7 @@
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.ServiceInfo;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Message;
@@ -165,7 +167,8 @@
// Thread currently set for VR scheduling
int mVrThreadTid;
- boolean mIsImeProcess;
+ // Whether this process has ever started a service with the BIND_INPUT_METHOD permission.
+ private volatile boolean mHasImeService;
// all activities running in the process
private final ArrayList<ActivityRecord> mActivities = new ArrayList<>();
@@ -187,6 +190,8 @@
// Registered display id as a listener to override config change
private int mDisplayId;
private ActivityRecord mConfigActivityRecord;
+ // Whether the activity config override is allowed for this process.
+ private volatile boolean mIsActivityConfigOverrideAllowed = true;
/**
* Activities that hosts some UI drawn by the current process. The activities live
* in another process. This is used to check if the process is currently showing anything
@@ -201,9 +206,6 @@
/** Whether our process is currently running a {@link IRemoteAnimationRunner} */
private boolean mRunningRemoteAnimation;
- /** Whether this process is owned by the System UI package. */
- final boolean mIsSysUiPackage;
-
public WindowProcessController(@NonNull ActivityTaskManagerService atm, ApplicationInfo info,
String name, int uid, int userId, Object owner, WindowProcessListener listener) {
mInfo = info;
@@ -215,8 +217,13 @@
mAtm = atm;
mDisplayId = INVALID_DISPLAY;
- mIsSysUiPackage = info.packageName.equals(
+ boolean isSysUiPackage = info.packageName.equals(
mAtm.getSysUiServiceComponentLocked().getPackageName());
+ if (isSysUiPackage || mUid == Process.SYSTEM_UID) {
+ // This is a system owned process and should not use an activity config.
+ // TODO(b/151161907): Remove after support for display-independent (raw) SysUi configs.
+ mIsActivityConfigOverrideAllowed = false;
+ }
onConfigurationChanged(atm.getGlobalConfiguration());
}
@@ -1095,9 +1102,7 @@
* always track the configuration of the non-finishing activity last added to the process.
*/
private void updateActivityConfigurationListener() {
- if (mIsSysUiPackage || mUid == Process.SYSTEM_UID) {
- // This is a system owned process and should not use an activity config.
- // TODO(b/151161907): Remove after support for display-independent (raw) SysUi configs.
+ if (!mIsActivityConfigOverrideAllowed) {
return;
}
@@ -1132,7 +1137,7 @@
final Configuration config = getConfiguration();
if (mLastReportedConfiguration.diff(config) == 0) {
// Nothing changed.
- if (Build.IS_DEBUGGABLE && mIsImeProcess) {
+ if (Build.IS_DEBUGGABLE && mHasImeService) {
// TODO (b/135719017): Temporary log for debugging IME service.
Slog.w(TAG_CONFIGURATION, "Current config: " + config
+ " unchanged for IME proc " + mName);
@@ -1156,7 +1161,7 @@
private void dispatchConfigurationChange(Configuration config) {
if (mThread == null) {
- if (Build.IS_DEBUGGABLE && mIsImeProcess) {
+ if (Build.IS_DEBUGGABLE && mHasImeService) {
// TODO (b/135719017): Temporary log for debugging IME service.
Slog.w(TAG_CONFIGURATION, "Unable to send config for IME proc " + mName
+ ": no app thread");
@@ -1166,7 +1171,7 @@
if (DEBUG_CONFIGURATION) {
Slog.v(TAG_CONFIGURATION, "Sending to proc " + mName + " new config " + config);
}
- if (Build.IS_DEBUGGABLE && mIsImeProcess) {
+ if (Build.IS_DEBUGGABLE && mHasImeService) {
// TODO (b/135719017): Temporary log for debugging IME service.
Slog.v(TAG_CONFIGURATION, "Sending to IME proc " + mName + " new config " + config);
}
@@ -1286,6 +1291,35 @@
}
}
+ /**
+ * Called to notify {@link WindowProcessController} of a started service.
+ *
+ * @param serviceInfo information describing the started service.
+ */
+ public void onServiceStarted(ServiceInfo serviceInfo) {
+ String permission = serviceInfo.permission;
+ if (permission == null) {
+ return;
+ }
+
+ // TODO: Audit remaining services for disabling activity override (Wallpaper, Dream, etc).
+ switch (permission) {
+ case Manifest.permission.BIND_INPUT_METHOD:
+ mHasImeService = true;
+ // Fall-through
+ case Manifest.permission.BIND_ACCESSIBILITY_SERVICE:
+ case Manifest.permission.BIND_VOICE_INTERACTION:
+ // We want to avoid overriding the config of these services with that of the
+ // activity as it could lead to incorrect display metrics. For ex, IME services
+ // expect their config to match the config of the display with the IME window
+ // showing.
+ mIsActivityConfigOverrideAllowed = false;
+ break;
+ default:
+ break;
+ }
+ }
+
@HotPath(caller = HotPath.OOM_ADJUSTMENT)
public void onTopProcChanged() {
synchronized (mAtm.mGlobalLockWithoutBoost) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 7a175ca1..2983d58 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -541,7 +541,7 @@
doReturn(new ArrayMap<IBinder, ArrayList<ConnectionRecord>>()).when(s).getConnections();
s.startRequested = true;
s.lastActivity = SystemClock.uptimeMillis();
- app.services.add(s);
+ app.startService(s);
sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -585,7 +585,7 @@
doReturn(new ArrayMap<IBinder, ArrayList<ConnectionRecord>>()).when(s).getConnections();
s.startRequested = true;
s.lastActivity = SystemClock.uptimeMillis();
- app.services.add(s);
+ app.startService(s);
sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
@@ -1593,7 +1593,7 @@
s.app = app3;
setFieldValue(ServiceRecord.class, s, "connections",
new ArrayMap<IBinder, ArrayList<ConnectionRecord>>());
- app3.services.add(s);
+ app3.startService(s);
doCallRealMethod().when(s).getConnections();
s.startRequested = true;
s.lastActivity = now;
@@ -1698,7 +1698,7 @@
record.app = service;
setFieldValue(ServiceRecord.class, record, "connections",
new ArrayMap<IBinder, ArrayList<ConnectionRecord>>());
- service.services.add(record);
+ service.startService(record);
doCallRealMethod().when(record).getConnections();
}
AppBindRecord binding = new AppBindRecord(record, null, client);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index 07a6179..cdf8eb4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -28,9 +28,11 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
+import android.Manifest;
import android.app.IApplicationThread;
import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
+import android.content.pm.ServiceInfo;
import android.content.res.Configuration;
import android.platform.test.annotations.Presubmit;
@@ -200,6 +202,57 @@
assertFalse(wpc.registeredForActivityConfigChanges());
}
+ @Test
+ public void testActivityNotOverridingImeProcessConfig() {
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.permission = Manifest.permission.BIND_INPUT_METHOD;
+ // Notify WPC that this process has started an IME service.
+ mWpc.onServiceStarted(serviceInfo);
+
+ final ActivityRecord activity = new ActivityBuilder(mService)
+ .setCreateTask(true)
+ .setUseProcess(mWpc)
+ .build();
+
+ mWpc.addActivityIfNeeded(activity);
+ // IME processes should not be registered for activity config changes.
+ assertFalse(mWpc.registeredForActivityConfigChanges());
+ }
+
+ @Test
+ public void testActivityNotOverridingAllyProcessConfig() {
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.permission = Manifest.permission.BIND_ACCESSIBILITY_SERVICE;
+ // Notify WPC that this process has started an ally service.
+ mWpc.onServiceStarted(serviceInfo);
+
+ final ActivityRecord activity = new ActivityBuilder(mService)
+ .setCreateTask(true)
+ .setUseProcess(mWpc)
+ .build();
+
+ mWpc.addActivityIfNeeded(activity);
+ // Ally processes should not be registered for activity config changes.
+ assertFalse(mWpc.registeredForActivityConfigChanges());
+ }
+
+ @Test
+ public void testActivityNotOverridingVoiceInteractionProcessConfig() {
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.permission = Manifest.permission.BIND_VOICE_INTERACTION;
+ // Notify WPC that this process has started an voice interaction service.
+ mWpc.onServiceStarted(serviceInfo);
+
+ final ActivityRecord activity = new ActivityBuilder(mService)
+ .setCreateTask(true)
+ .setUseProcess(mWpc)
+ .build();
+
+ mWpc.addActivityIfNeeded(activity);
+ // Voice interaction service processes should not be registered for activity config changes.
+ assertFalse(mWpc.registeredForActivityConfigChanges());
+ }
+
private TestDisplayContent createTestDisplayContentInContainer() {
return new TestDisplayContent.Builder(mService, 1000, 1500).build();
}