From a098222fb767b4b9919286e2a8d23225d57a6abd Mon Sep 17 00:00:00 2001 From: Darryl L Johnson Date: Tue, 18 Feb 2020 18:21:51 -0800 Subject: [PATCH] Prevent activity config override for system processes. To improve app compatibility in multi-display and multi-window environments WM overrides the process config with the config of the most recently launched activity. However, doing so has caused issues with system applications (notably System UI) who currently rely on this config. This change ensures that system processes and system ui do not receive this compatibility override and revert back to the old functionality. In the future this will be replaced with dedicated channels to report display configurations. Test: WindowProcessControllerTests Test: ActivityRecordTests Bug: 148675523 Fixes: 148675523 Change-Id: I811d4f60c1e79b5526a5f9e9973b8d6355ee8c15 --- .../server/wm/ActivityTaskManagerService.java | 10 +++++++ .../server/wm/WindowProcessController.java | 14 ++++++++++ .../server/am/ApplicationExitInfoTest.java | 3 +++ .../server/am/MockingOomAdjusterTests.java | 10 +++++++ .../server/wm/ActivityStarterTests.java | 7 +++-- .../server/wm/LaunchParamsPersisterTests.java | 1 + .../server/wm/SystemServicesTestRule.java | 4 +++ .../wm/WindowProcessControllerTests.java | 26 ++++++++++++++++++- 8 files changed, 72 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 21d300aba1b9e..7bacc427feb83 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -356,6 +356,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { ActivityManagerInternal mAmInternal; UriGrantsManagerInternal mUgmInternal; private PackageManagerInternal mPmInternal; + /** The cached sys ui service component name from package manager. */ + private ComponentName mSysUiServiceComponent; private PermissionPolicyInternal mPermissionPolicyInternal; @VisibleForTesting final ActivityTaskManagerInternal mInternal; @@ -5869,6 +5871,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return mPmInternal; } + ComponentName getSysUiServiceComponentLocked() { + if (mSysUiServiceComponent == null) { + final PackageManagerInternal pm = getPackageManagerInternalLocked(); + mSysUiServiceComponent = pm.getSystemUiServiceComponent(); + } + return mSysUiServiceComponent; + } + PermissionPolicyInternal getPermissionPolicyInternal() { if (mPermissionPolicyInternal == null) { mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class); diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index 833bb83acb309..32eb932ea0ed4 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -53,6 +53,7 @@ import android.content.pm.ApplicationInfo; import android.content.res.Configuration; import android.os.Build; import android.os.Message; +import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.util.ArraySet; @@ -200,6 +201,9 @@ public class WindowProcessController extends ConfigurationContainer= 0; i--) { final ActivityRecord activityRecord = mActivities.get(i); if (!activityRecord.finishing && !activityRecord.containsListener(this)) { diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java index 95f4e832cd2d6..c45ee7b4d8026 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java @@ -55,6 +55,7 @@ import android.system.OsConstants; import android.text.TextUtils; import android.util.Pair; +import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.appop.AppOpsService; import com.android.server.wm.ActivityTaskManagerService; @@ -125,6 +126,8 @@ public class ApplicationExitInfoTest { mAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper()); mAms.mAtmInternal = spy(mAms.mActivityTaskManager.getAtmInternal()); mAms.mPackageManagerInt = mPackageManagerInt; + doReturn(new ComponentName("", "")).when(mPackageManagerInt).getSystemUiServiceComponent(); + LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt); } @After 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 fc2ae40daca0f..d764a790172cc 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java @@ -75,8 +75,10 @@ import static org.mockito.Mockito.spy; import android.app.IApplicationThread; import android.app.IServiceConnection; +import android.content.ComponentName; import android.content.Context; import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManagerInternal; import android.content.pm.ServiceInfo; import android.os.Build; import android.os.IBinder; @@ -87,6 +89,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.SparseArray; +import com.android.server.LocalServices; import com.android.server.wm.ActivityServiceConnectionsHolder; import com.android.server.wm.ActivityTaskManagerService; import com.android.server.wm.WindowProcessController; @@ -127,6 +130,7 @@ public class MockingOomAdjusterTests { private static final String MOCKAPP5_PROCESSNAME = "test #5"; private static final String MOCKAPP5_PACKAGENAME = "com.android.test.test5"; private static Context sContext; + private static PackageManagerInternal sPackageManagerInternal; private static ActivityManagerService sService; @BeforeClass @@ -134,9 +138,15 @@ public class MockingOomAdjusterTests { sContext = getInstrumentation().getTargetContext(); System.setProperty("dexmaker.share_classloader", "true"); + sPackageManagerInternal = mock(PackageManagerInternal.class); + doReturn(new ComponentName("", "")).when(sPackageManagerInternal) + .getSystemUiServiceComponent(); + LocalServices.addService(PackageManagerInternal.class, sPackageManagerInternal); + sService = mock(ActivityManagerService.class); sService.mActivityTaskManager = new ActivityTaskManagerService(sContext); sService.mActivityTaskManager.initialize(null, null, sContext.getMainLooper()); + sService.mPackageManagerInt = sPackageManagerInternal; sService.mAtmInternal = spy(sService.mActivityTaskManager.getAtmInternal()); sService.mConstants = new ActivityManagerConstants(sContext, sService, diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java index 1c267a03c1211..6eec649f2ba54 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -203,10 +203,11 @@ public class ActivityStarterTests extends ActivityTestsBase { final IApplicationThread caller = mock(IApplicationThread.class); final WindowProcessListener listener = mock(WindowProcessListener.class); + final ApplicationInfo ai = new ApplicationInfo(); + ai.packageName = "com.android.test.package"; final WindowProcessController wpc = containsConditions(preconditions, PRECONDITION_NO_CALLER_APP) - ? null : new WindowProcessController( - service, mock(ApplicationInfo.class), null, 0, -1, null, listener); + ? null : new WindowProcessController(service, ai, null, 0, -1, null, listener); doReturn(wpc).when(service).getProcessController(anyObject()); final Intent intent = new Intent(); @@ -345,6 +346,7 @@ public class ActivityStarterTests extends ActivityTestsBase { doReturn(false).when(mMockPackageManager).isInstantAppInstallerComponent(any()); doReturn(null).when(mMockPackageManager).resolveIntent(any(), any(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyInt()); + doReturn(new ComponentName("", "")).when(mMockPackageManager).getSystemUiServiceComponent(); // Never review permissions doReturn(false).when(mMockPackageManager).isPermissionsReviewRequired(any(), anyInt()); @@ -656,6 +658,7 @@ public class ActivityStarterTests extends ActivityTestsBase { final WindowProcessListener listener = mock(WindowProcessListener.class); final ApplicationInfo ai = new ApplicationInfo(); ai.uid = callingUid; + ai.packageName = "com.android.test.package"; final WindowProcessController callerApp = new WindowProcessController(mService, ai, null, callingUid, -1, null, listener); callerApp.setHasForegroundActivities(hasForegroundActivities); diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java index ac4c228fda9af..12d89de8e9ad1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java @@ -131,6 +131,7 @@ public class LaunchParamsPersisterTests extends ActivityTestsBase { LocalServices.addService(PackageManagerInternal.class, mMockPmi); when(mMockPmi.getPackageList(any())).thenReturn(new PackageList( Collections.singletonList(TEST_COMPONENT.getPackageName()), /* observer */ null)); + when(mMockPmi.getSystemUiServiceComponent()).thenReturn(new ComponentName("", "")); mTarget.onSystemReady(); final ArgumentCaptor observerCaptor = diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java index 55d12dbd0abb0..560d03fe7d9ef 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java @@ -40,6 +40,7 @@ import android.app.ActivityManagerInternal; import android.app.AppOpsManager; import android.app.usage.UsageStatsManagerInternal; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.IntentFilter; @@ -213,6 +214,9 @@ public class SystemServicesTestRule implements TestRule { anyString(), anyInt()); doReturn(null).when(packageManagerInternal).getDefaultHomeActivity(anyInt()); + ComponentName systemServiceComponent = new ComponentName("android.test.system.service", ""); + doReturn(systemServiceComponent).when(packageManagerInternal).getSystemUiServiceComponent(); + // PowerManagerInternal final PowerManagerInternal pmi = mock(PowerManagerInternal.class); final PowerSaveState state = new PowerSaveState.Builder().build(); 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 34e487bc1e947..07a6179c00bdf 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java @@ -29,6 +29,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; import android.app.IApplicationThread; +import android.content.ComponentName; import android.content.pm.ApplicationInfo; import android.content.res.Configuration; import android.platform.test.annotations.Presubmit; @@ -55,8 +56,11 @@ public class WindowProcessControllerTests extends ActivityTestsBase { @Before public void setUp() { mMockListener = mock(WindowProcessListener.class); + + ApplicationInfo info = mock(ApplicationInfo.class); + info.packageName = "test.package.name"; mWpc = new WindowProcessController( - mService, mock(ApplicationInfo.class), null, 0, -1, null, mMockListener); + mService, info, null, 0, -1, null, mMockListener); mWpc.setThread(mock(IApplicationThread.class)); } @@ -176,6 +180,26 @@ public class WindowProcessControllerTests extends ActivityTestsBase { assertEquals(mWpc.getLastReportedConfiguration(), newConfig); } + @Test + public void testActivityNotOverridingSystemUiProcessConfig() { + final ComponentName systemUiServiceComponent = mService.getSysUiServiceComponentLocked(); + ApplicationInfo applicationInfo = mock(ApplicationInfo.class); + applicationInfo.packageName = systemUiServiceComponent.getPackageName(); + + WindowProcessController wpc = new WindowProcessController( + mService, applicationInfo, null, 0, -1, null, mMockListener); + wpc.setThread(mock(IApplicationThread.class)); + + final ActivityRecord activity = new ActivityBuilder(mService) + .setCreateTask(true) + .setUseProcess(wpc) + .build(); + + wpc.addActivityIfNeeded(activity); + // System UI owned processes should not be registered for activity config changes. + assertFalse(wpc.registeredForActivityConfigChanges()); + } + private TestDisplayContent createTestDisplayContentInContainer() { return new TestDisplayContent.Builder(mService, 1000, 1500).build(); }