diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index e6bc79679a8f2..5a40b30551b61 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -1447,6 +1447,16 @@ abstract public class ManagedServices { } } + @VisibleForTesting + void reregisterService(final ComponentName cn, final int userId) { + // If rebinding a package that died, ensure it still has permission + // after the rebind delay + if (isPackageOrComponentAllowed(cn.getPackageName(), userId) + || isPackageOrComponentAllowed(cn.flattenToString(), userId)) { + registerService(cn, userId); + } + } + /** * Inject a system service into the management list. */ @@ -1545,12 +1555,9 @@ abstract public class ManagedServices { unbindService(this, name, userid); if (!mServicesRebinding.contains(servicesBindingTag)) { mServicesRebinding.add(servicesBindingTag); - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - registerService(name, userid); - } - }, ON_BINDING_DIED_REBIND_DELAY_MS); + mHandler.postDelayed(() -> + reregisterService(name, userid), + ON_BINDING_DIED_REBIND_DELAY_MS); } else { Slog.v(TAG, getCaption() + " not rebinding in user " + userid + " as a previous rebind attempt was made: " + name); 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 2f054b004d420..8ba9af0d85d09 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java @@ -839,6 +839,156 @@ public class ManagedServicesTest extends UiServiceTestCase { verifyExpectedBoundEntries(service, false); } + @Test + public void reregisterService_checksAppIsApproved_pkg() throws Exception { + 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_PACKAGE); + 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.addApprovedList("a", 0, true); + + service.reregisterService(cn, 0); + + assertTrue(service.isBound(cn, 0)); + } + + @Test + public void reregisterService_checksAppIsApproved_pkg_secondary() throws Exception { + 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_PACKAGE); + 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.addApprovedList("a", 0, false); + + service.reregisterService(cn, 0); + + assertTrue(service.isBound(cn, 0)); + } + + @Test + public void reregisterService_checksAppIsApproved_cn() throws Exception { + 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.addApprovedList("a/a", 0, true); + + service.reregisterService(cn, 0); + + assertTrue(service.isBound(cn, 0)); + } + + @Test + public void reregisterService_checksAppIsApproved_cn_secondary() throws Exception { + 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.addApprovedList("a/a", 0, false); + + service.reregisterService(cn, 0); + + assertTrue(service.isBound(cn, 0)); + } + + @Test + public void reregisterService_checksAppIsNotApproved_cn_secondary() throws Exception { + 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.addApprovedList("b/b", 0, false); + + service.reregisterService(cn, 0); + + assertFalse(service.isBound(cn, 0)); + } + @Test public void unbindOtherUserServices() throws PackageManager.NameNotFoundException { Context context = mock(Context.class);