OSDN Git Service

Clear calling identity before verifying listeners
authorJulia Reynolds <juliacr@google.com>
Wed, 12 Apr 2017 13:41:16 +0000 (09:41 -0400)
committergitbuildkicker <android-build@google.com>
Wed, 12 Apr 2017 19:54:30 +0000 (12:54 -0700)
Also don't throw when can't verify listener.

And update mocking in tests to clean state between tests.

Bug: 36783632
Fixes: 37263567
Test: runtest-systemui-notification, create a secondary user
Change-Id: I5ec95539c9859b67b8fbc7e6a85334e08e6b5a98
(cherry picked from commit da78147f290cbafe0c36aef28ab15fcefce74e39)

services/core/java/com/android/server/notification/NotificationManagerService.java
services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java

index 3c46e05..2c7a61b 100644 (file)
@@ -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);
+                    }
+                });
             }
         }
 
index 6aa8f3a..07e4bb8 100644 (file)
@@ -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);
+    }
 }