From 0b4f7bd445d91dec05b8ec9ae672c831e2909731 Mon Sep 17 00:00:00 2001 From: Zhen Zhang Date: Mon, 3 Aug 2020 19:12:59 -0700 Subject: [PATCH] Unbind background users' components in ManagedServices on user switched Include background users' components to the set of service components to unbind on user switched. These components will be bound again when their user becomes foreground user. Added unit test Bug: 167633441 Test: atest ManagedServicesTest Change-Id: Ibc81cc35205075187c22fd3a4ed82b373f211038 --- .../server/notification/ManagedServices.java | 25 +++++++++++++- .../notification/ManagedServicesTest.java | 33 +++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index 74b7bd76b0471..4040f4189698d 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -833,6 +833,7 @@ abstract public class ManagedServices { public void onUserSwitched(int user) { if (DEBUG) Slog.d(TAG, "onUserSwitched u=" + user); + unbindOtherUserServices(user); rebindServices(true, user); } @@ -1219,6 +1220,27 @@ abstract public class ManagedServices { bindToServices(componentsToBind); } + /** + * Called when user switched to unbind all services from other users. + */ + @VisibleForTesting + void unbindOtherUserServices(int currentUser) { + final SparseArray> componentsToUnbind = new SparseArray<>(); + + synchronized (mMutex) { + final Set removableBoundServices = getRemovableConnectedServices(); + for (ManagedServiceInfo info : removableBoundServices) { + if (info.userid != currentUser) { + Set toUnbind = + componentsToUnbind.get(info.userid, new ArraySet<>()); + toUnbind.add(info.component); + componentsToUnbind.put(info.userid, toUnbind); + } + } + } + unbindFromServices(componentsToUnbind); + } + protected void unbindFromServices(SparseArray> componentsToUnbind) { for (int i = 0; i < componentsToUnbind.size(); i++) { final int userId = componentsToUnbind.keyAt(i); @@ -1264,7 +1286,8 @@ abstract public class ManagedServices { /** * Version of registerService that takes the name of a service component to bind to. */ - private void registerService(final ComponentName name, final int userid) { + @VisibleForTesting + void registerService(final ComponentName name, final int userid) { synchronized (mMutex) { registerServiceLocked(name, userid); } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java index d7e431f3bb51c..e304083dfd27e 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java @@ -689,6 +689,39 @@ public class ManagedServicesTest extends UiServiceTestCase { verifyExpectedBoundEntries(service, false); } + @Test + public void unbindOtherUserServices() throws PackageManager.NameNotFoundException { + Context context = mock(Context.class); + PackageManager pm = mock(PackageManager.class); + ApplicationInfo ai = new ApplicationInfo(); + ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; + + when(context.getPackageName()).thenReturn(mContext.getPackageName()); + when(context.getUserId()).thenReturn(mContext.getUserId()); + when(context.getPackageManager()).thenReturn(pm); + when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai); + + ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm, + APPROVAL_BY_COMPONENT); + ComponentName cn = ComponentName.unflattenFromString("a/a"); + + when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> { + Object[] args = invocation.getArguments(); + ServiceConnection sc = (ServiceConnection) args[1]; + sc.onServiceConnected(cn, mock(IBinder.class)); + return true; + }); + + service.registerService(cn, 0); + service.registerService(cn, 10); + service.registerService(cn, 11); + service.unbindOtherUserServices(11); + + assertFalse(service.isBound(cn, 0)); + assertFalse(service.isBound(cn, 10)); + assertTrue(service.isBound(cn, 11)); + } + @Test public void testPackageUninstall_packageNoLongerInApprovedList() throws Exception { for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {