diff options
2 files changed, 70 insertions, 46 deletions
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 3c46e05cb70d..2c7a61b0318e 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -2695,7 +2695,9 @@ public class NotificationManagerService extends SystemService { Preconditions.checkNotNull(channel); ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token); - checkHasCompanionDevice(info); + if (!hasCompanionDevice(info)) { + throw new SecurityException(info + " does not have access"); + } int uid = mPackageManager.getPackageUid(pkg, 0, info.userid); updateNotificationChannelInt(pkg, uid, channel, true); @@ -2705,7 +2707,9 @@ public class NotificationManagerService extends SystemService { public ParceledListSlice<NotificationChannel> getNotificationChannelsFromPrivilegedListener( INotificationListener token, String pkg) throws RemoteException { ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token); - checkHasCompanionDevice(info); + if (!hasCompanionDevice(info)) { + throw new SecurityException(info + " does not have access"); + } int uid = mPackageManager.getPackageUid(pkg, 0, info.userid); return mRankingHelper.getNotificationChannels(pkg, uid, false /* includeDeleted */); @@ -2716,7 +2720,9 @@ public class NotificationManagerService extends SystemService { getNotificationChannelGroupsFromPrivilegedListener( INotificationListener token, String pkg) throws RemoteException { ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token); - checkHasCompanionDevice(info); + if (!hasCompanionDevice(info)) { + throw new SecurityException(info + " does not have access"); + } List<NotificationChannelGroup> groups = new ArrayList<>(); int uid = mPackageManager.getPackageUid(pkg, 0, info.userid); @@ -4655,15 +4661,28 @@ public class NotificationManagerService extends SystemService { channels, overridePeople, snoozeCriteria, showBadge); } - private void checkHasCompanionDevice(ManagedServiceInfo info) throws RemoteException { + boolean hasCompanionDevice(ManagedServiceInfo info) { if (mCompanionManager == null) { mCompanionManager = ICompanionDeviceManager.Stub.asInterface( ServiceManager.getService(Context.COMPANION_DEVICE_SERVICE)); } - if (ArrayUtils.isEmpty(mCompanionManager.getAssociations( - info.component.getPackageName(), info.userid))) { - throw new SecurityException("Disallowed call from " + info.component); + long identity = Binder.clearCallingIdentity(); + try { + List<String> associations = mCompanionManager.getAssociations( + info.component.getPackageName(), info.userid); + if (!ArrayUtils.isEmpty(associations)) { + return true; + } + } catch (SecurityException se) { + // Not a privileged listener + } catch (RemoteException re) { + Slog.e(TAG, "Cannot reach companion device service", re); + } catch (Exception e) { + Slog.e(TAG, "Cannot verify listener " + info, e); + } finally { + Binder.restoreCallingIdentity(identity); } + return false; } private boolean isVisibleToListener(StatusBarNotification sbn, ManagedServiceInfo listener) { @@ -4996,23 +5015,19 @@ public class NotificationManagerService extends SystemService { return; } for (final ManagedServiceInfo serviceInfo : getServices()) { - if (!serviceInfo.isEnabledForCurrentProfiles()) { + if (!serviceInfo.enabledAndUserMatches(UserHandle.getCallingUserId())) { continue; } - try { - checkHasCompanionDevice(serviceInfo); - mHandler.post(new Runnable() { - @Override - public void run() { - notifyNotificationChannelChanged(serviceInfo, pkg, channel, - modificationType); - } - }); - } catch (SecurityException se) { - // Not a privileged listener; do not notify - } catch (RemoteException e) { - Slog.e(TAG, "Cannot reach companion device service", e); + if (!hasCompanionDevice(serviceInfo)) { + continue; } + mHandler.post(new Runnable() { + @Override + public void run() { + notifyNotificationChannelChanged(serviceInfo, pkg, channel, + modificationType); + } + }); } } @@ -5022,23 +5037,19 @@ public class NotificationManagerService extends SystemService { return; } for (final ManagedServiceInfo serviceInfo : getServices()) { - if (!serviceInfo.isEnabledForCurrentProfiles()) { + if (!serviceInfo.enabledAndUserMatches(UserHandle.getCallingUserId())) { continue; } - try { - checkHasCompanionDevice(serviceInfo); - mHandler.post(new Runnable() { - @Override - public void run() { - notifyNotificationChannelGroupChanged(serviceInfo, pkg, group, - modificationType); - } - }); - } catch (SecurityException se) { - // Not a privileged listener; do not notify - } catch (RemoteException e) { - Slog.e(TAG, "Cannot reach companion device service", e); + if (!hasCompanionDevice(serviceInfo)) { + continue; } + mHandler.post(new Runnable() { + @Override + public void run() { + notifyNotificationChannelGroupChanged(serviceInfo, pkg, group, + modificationType); + } + }); } } diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java index 6aa8f3a8010e..07e4bb831d41 100644 --- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -59,10 +59,11 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; import com.android.server.lights.Light; import com.android.server.lights.LightsManager; @@ -74,20 +75,21 @@ public class NotificationManagerServiceTest { private NotificationManagerService mNotificationManagerService; private INotificationManager mBinderService; private NotificationManagerInternal mInternalService; - private IPackageManager mPackageManager = mock(IPackageManager.class); - private final PackageManager mPackageManagerClient = mock(PackageManager.class); + @Mock + private IPackageManager mPackageManager; + @Mock + private PackageManager mPackageManagerClient; private Context mContext = InstrumentationRegistry.getTargetContext(); private final String PKG = mContext.getPackageName(); private TestableLooper mTestableLooper; - private final RankingHelper mRankingHelper = mock(RankingHelper.class); + @Mock + private RankingHelper mRankingHelper; private NotificationChannel mTestNotificationChannel = new NotificationChannel( TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT); - private NotificationManagerService.NotificationListeners mNotificationListeners = - mock(NotificationManagerService.NotificationListeners.class); - private ManagedServices.ManagedServiceInfo mListener = - mNotificationListeners.new ManagedServiceInfo( - null, new ComponentName(PKG, "test_class"), uid, true, null, 0); - private ICompanionDeviceManager mCompanionMgr = mock(ICompanionDeviceManager.class); + @Mock + private NotificationManagerService.NotificationListeners mNotificationListeners; + private ManagedServices.ManagedServiceInfo mListener; + @Mock private ICompanionDeviceManager mCompanionMgr; // Use a Testable subclass so we can simulate calls from the system without failing. private static class TestableNotificationManagerService extends NotificationManagerService { @@ -102,6 +104,7 @@ public class NotificationManagerServiceTest { @Before @UiThreadTest public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); mNotificationManagerService = new TestableNotificationManagerService(mContext); // MockPackageManager - default returns ApplicationInfo with matching calling UID @@ -116,6 +119,8 @@ public class NotificationManagerServiceTest { // Use this testable looper. mTestableLooper = new TestableLooper(false); + mListener = mNotificationListeners.new ManagedServiceInfo( + null, new ComponentName(PKG, "test_class"), uid, true, null, 0); when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener); mNotificationManagerService.init(mTestableLooper.getLooper(), mPackageManager, mPackageManagerClient, mockLightsManager, mNotificationListeners, mCompanionMgr); @@ -631,4 +636,12 @@ public class NotificationManagerServiceTest { verify(mRankingHelper, never()).getNotificationChannelGroups(anyString(), anyInt()); } + + @Test + @UiThreadTest + public void testHasCompanionDevice_failure() throws Exception { + when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow( + new IllegalArgumentException()); + mNotificationManagerService.hasCompanionDevice(mListener); + } } |