diff options
| author | 2020-04-17 11:52:50 -0700 | |
|---|---|---|
| committer | 2020-04-21 12:40:56 -0700 | |
| commit | d02044c3ce91fc396aed87a7dc7a126b52f89b32 (patch) | |
| tree | 886f4b4c190dec215090fd34de410c2c6a1964f1 | |
| parent | a8761169674661abc5b8dabf231e235f9e69357f (diff) | |
Disable activity process config override for certain display-based services.
Single session IME services expect their config to be overriden with the
display the IME window is currently on while launching an activity on a
different display will trigger the compat logic to override the config
with the recent display.
A11y and voice interaction services can also have their display config
overriden with activity launches.
Test: WindowProcessControllerTests
Test: MockingOomAdjusterTests
Test: ProcessRecordTests
Test: ActivityManagerServiceTest
Test: OomAdjusterTests
Fixes: 153843194
Change-Id: Ibe0dd25d11935d07362dcfe95f338deda6d6e3da
9 files changed, 210 insertions, 72 deletions
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 21760cdf02eb..419389f7abef 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.PrintWriter; 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 @@ public final class ActiveServices { 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 @@ public final class ActiveServices { 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 @@ public final class ActiveServices { } 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 @@ public final class ActiveServices { 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 @@ public final class ActiveServices { // Cleanup. if (newService) { - app.services.remove(r); + app.stopService(r); r.setProcess(null); } @@ -3362,7 +3361,7 @@ public final class ActiveServices { 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 @@ public final class ActiveServices { } 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 @@ public final class ActiveServices { 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 @@ public final class ActiveServices { 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 @@ public final class ActiveServices { 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 @@ public final class ActiveServices { 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 @@ public final class ActiveServices { } if (!allowRestart) { - app.services.clear(); + app.stopAllServices(); app.clearBoundClientUids(); // Make sure there are no more restarting services for this process. @@ -4920,8 +4917,8 @@ public final class ActiveServices { 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 3fdf541566a5..9b2743ca6b1d 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 @@ public class ActivityManagerService extends IActivityManager.Stub 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 b1fc0296518b..50d2cab0af81 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 @@ class AppErrors { } // 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 2d6ef81faf1c..ad858533c430 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 @@ public final class OomAdjuster { 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 @@ public final class OomAdjuster { } 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 61ebc361b6af..a1ec07cda8a8 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 @@ class ProcessRecord implements WindowProcessListener { // 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 @@ class ProcessRecord implements WindowProcessListener { 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 @@ class ProcessRecord implements WindowProcessListener { } } + /** + * 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 @@ class ProcessRecord implements WindowProcessListener { 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 @@ class ProcessRecord implements WindowProcessListener { } 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 93a757449564..02f6a696f598 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 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } 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 194ed3ec3b0e..41bd70726e71 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.INSTRUMENTATION_K 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.Context; 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 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio // 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 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio // 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 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio /** 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 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio 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 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio * 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 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio 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 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio 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 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio 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 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio } } + /** + * 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 7a175ca1b7f5..2983d585c45a 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 @@ public class MockingOomAdjusterTests { 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 @@ public class MockingOomAdjusterTests { 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 @@ public class MockingOomAdjusterTests { 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 @@ public class MockingOomAdjusterTests { 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 07a6179c00bd..cdf8eb4faf1d 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.mock; 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 @@ public class WindowProcessControllerTests extends ActivityTestsBase { 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(); } |