Loading services/core/java/com/android/server/notification/NotificationManagerService.java +46 −35 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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 */); Loading @@ -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); Loading Loading @@ -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) { Loading Loading @@ -4996,11 +5015,12 @@ public class NotificationManagerService extends SystemService { return; } for (final ManagedServiceInfo serviceInfo : getServices()) { if (!serviceInfo.isEnabledForCurrentProfiles()) { if (!serviceInfo.enabledAndUserMatches(UserHandle.getCallingUserId())) { continue; } if (!hasCompanionDevice(serviceInfo)) { continue; } try { checkHasCompanionDevice(serviceInfo); mHandler.post(new Runnable() { @Override public void run() { Loading @@ -5008,11 +5028,6 @@ public class NotificationManagerService extends SystemService { modificationType); } }); } catch (SecurityException se) { // Not a privileged listener; do not notify } catch (RemoteException e) { Slog.e(TAG, "Cannot reach companion device service", e); } } } Loading @@ -5022,11 +5037,12 @@ public class NotificationManagerService extends SystemService { return; } for (final ManagedServiceInfo serviceInfo : getServices()) { if (!serviceInfo.isEnabledForCurrentProfiles()) { if (!serviceInfo.enabledAndUserMatches(UserHandle.getCallingUserId())) { continue; } if (!hasCompanionDevice(serviceInfo)) { continue; } try { checkHasCompanionDevice(serviceInfo); mHandler.post(new Runnable() { @Override public void run() { Loading @@ -5034,11 +5050,6 @@ public class NotificationManagerService extends SystemService { modificationType); } }); } catch (SecurityException se) { // Not a privileged listener; do not notify } catch (RemoteException e) { Slog.e(TAG, "Cannot reach companion device service", e); } } } Loading services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java +24 −11 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 { Loading @@ -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 Loading @@ -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); Loading Loading @@ -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); } } Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +46 −35 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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 */); Loading @@ -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); Loading Loading @@ -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) { Loading Loading @@ -4996,11 +5015,12 @@ public class NotificationManagerService extends SystemService { return; } for (final ManagedServiceInfo serviceInfo : getServices()) { if (!serviceInfo.isEnabledForCurrentProfiles()) { if (!serviceInfo.enabledAndUserMatches(UserHandle.getCallingUserId())) { continue; } if (!hasCompanionDevice(serviceInfo)) { continue; } try { checkHasCompanionDevice(serviceInfo); mHandler.post(new Runnable() { @Override public void run() { Loading @@ -5008,11 +5028,6 @@ public class NotificationManagerService extends SystemService { modificationType); } }); } catch (SecurityException se) { // Not a privileged listener; do not notify } catch (RemoteException e) { Slog.e(TAG, "Cannot reach companion device service", e); } } } Loading @@ -5022,11 +5037,12 @@ public class NotificationManagerService extends SystemService { return; } for (final ManagedServiceInfo serviceInfo : getServices()) { if (!serviceInfo.isEnabledForCurrentProfiles()) { if (!serviceInfo.enabledAndUserMatches(UserHandle.getCallingUserId())) { continue; } if (!hasCompanionDevice(serviceInfo)) { continue; } try { checkHasCompanionDevice(serviceInfo); mHandler.post(new Runnable() { @Override public void run() { Loading @@ -5034,11 +5050,6 @@ public class NotificationManagerService extends SystemService { modificationType); } }); } catch (SecurityException se) { // Not a privileged listener; do not notify } catch (RemoteException e) { Slog.e(TAG, "Cannot reach companion device service", e); } } } Loading
services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java +24 −11 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 { Loading @@ -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 Loading @@ -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); Loading Loading @@ -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); } }