Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bf3f4dd7 authored by Julia Reynolds's avatar Julia Reynolds Committed by android-build-merger
Browse files

Merge "Clear calling identity before verifying listeners" into oc-dev

am: 43dd3ba3

Change-Id: I05a728d069a06f4ec36dff79db022407f4d3504c
parents 79bc4101 43dd3ba3
Loading
Loading
Loading
Loading
+46 −35
Original line number Diff line number Diff line
@@ -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,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() {
@@ -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);
                }
            }
        }

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

+24 −11
Original line number Diff line number Diff line
@@ -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);
    }
}