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
This commit is contained in:
Zhen Zhang
2020-08-03 19:12:59 -07:00
parent fc97abcae2
commit 0b4f7bd445
2 changed files with 57 additions and 1 deletions

View File

@@ -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<Set<ComponentName>> componentsToUnbind = new SparseArray<>();
synchronized (mMutex) {
final Set<ManagedServiceInfo> removableBoundServices = getRemovableConnectedServices();
for (ManagedServiceInfo info : removableBoundServices) {
if (info.userid != currentUser) {
Set<ComponentName> toUnbind =
componentsToUnbind.get(info.userid, new ArraySet<>());
toUnbind.add(info.component);
componentsToUnbind.put(info.userid, toUnbind);
}
}
}
unbindFromServices(componentsToUnbind);
}
protected void unbindFromServices(SparseArray<Set<ComponentName>> 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);
}

View File

@@ -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}) {