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

Commit 7a6da315 authored by Terence Zhang's avatar Terence Zhang
Browse files

added call notif exemption to PostNotificationRunnable and enhanced relevant

tests
Test: NotificationManagerServiceTest
Fixes: 227456870

Change-Id: Ib96c375a1bf69a77839fa35275d9364929522239
parent f944c485
Loading
Loading
Loading
Loading
+17 −3
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ import static android.content.Context.BIND_AUTO_CREATE;
import static android.content.Context.BIND_FOREGROUND_SERVICE;
import static android.content.Context.BIND_NOT_PERCEPTIBLE;
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
import static android.content.pm.PackageManager.FEATURE_TELECOM;
import static android.content.pm.PackageManager.FEATURE_TELEVISION;
import static android.content.pm.PackageManager.MATCH_ALL;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
@@ -2161,6 +2162,11 @@ public class NotificationManagerService extends SystemService {
        mAccessibilityManager = am;
    }
    @VisibleForTesting
    void setTelecomManager(TelecomManager tm) {
        mTelecomManager = tm;
    }
    // TODO: All tests should use this init instead of the one-off setters above.
    @VisibleForTesting
    void init(WorkerHandler handler, RankingHandler rankingHandler,
@@ -6978,8 +6984,13 @@ public class NotificationManagerService extends SystemService {
    private boolean isCallNotification(String pkg, int uid) {
        final long identity = Binder.clearCallingIdentity();
        try {
            return mTelecomManager.isInManagedCall() || mTelecomManager.isInSelfManagedCall(
            if (mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)
                    && mTelecomManager != null) {
                return mTelecomManager.isInManagedCall()
                        || mTelecomManager.isInSelfManagedCall(
                                pkg, UserHandle.getUserHandleForUid(uid));
            }
            return false;
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
@@ -7405,6 +7416,7 @@ public class NotificationManagerService extends SystemService {
        @Override
        public void run() {
            boolean appBanned = !areNotificationsEnabledForPackageInt(pkg, uid);
            boolean isCallNotification = isCallNotification(pkg, uid);
            synchronized (mNotificationLock) {
                try {
                    NotificationRecord r = null;
@@ -7423,8 +7435,10 @@ public class NotificationManagerService extends SystemService {
                    final StatusBarNotification n = r.getSbn();
                    final Notification notification = n.getNotification();
                    boolean isCallNotificationAndCorrectStyle = isCallNotification
                            && notification.isStyle(Notification.CallStyle.class);
                    if (!notification.isMediaNotification()
                    if (!(notification.isMediaNotification() || isCallNotificationAndCorrectStyle)
                            && (appBanned || isRecordBlockedLocked(r))) {
                        mUsageStats.registerBlocked(r);
                        if (DBG) {
+115 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.app.PendingIntent.FLAG_MUTABLE;
import static android.app.PendingIntent.FLAG_ONE_SHOT;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.PackageManager.FEATURE_TELECOM;
import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -448,6 +449,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
        mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
        when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0});

        when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(true);

        ActivityManager.AppTask task = mock(ActivityManager.AppTask.class);
        List<ActivityManager.AppTask> taskList = new ArrayList<>();
        ActivityManager.RecentTaskInfo taskInfo = new ActivityManager.RecentTaskInfo();
@@ -9194,6 +9197,118 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                r.getSbn().getPackageName(), r.getUser())).thenReturn(true);
        assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
                r.getSbn().getId(), r.getSbn().getTag(), r, false)).isTrue();

        // set telecom manager to null - blocked
        mService.setTelecomManager(null);
        assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
                           r.getSbn().getId(), r.getSbn().getTag(), r, false))
                .isFalse();

        // set telecom feature to false - blocked
        when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(false);
        assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
                           r.getSbn().getId(), r.getSbn().getTag(), r, false))
                .isFalse();
    }

    @Test
    public void testCallNotificationsBypassBlock_atPost() throws Exception {
        when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
        when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);

        Notification.Builder nb =
                new Notification.Builder(mContext, mTestNotificationChannel.getId())
                        .setContentTitle("foo")
                        .setSmallIcon(android.R.drawable.sym_def_app_icon)
                        .addAction(new Notification.Action.Builder(null, "test", null).build());
        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
                nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
        NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);

        mBinderService.setNotificationsEnabledForPackage(
                r.getSbn().getPackageName(), r.getUid(), false);

        // normal blocked notifications - blocked
        mService.addEnqueuedNotification(r);
        NotificationManagerService.PostNotificationRunnable runnable =
                mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(),
                        r.getUid(), SystemClock.elapsedRealtime());
        runnable.run();
        waitForIdle();

        verify(mUsageStats).registerBlocked(any());
        verify(mUsageStats, never()).registerPostedByApp(any());

        // just using the style - blocked
        mService.clearNotifications();
        reset(mUsageStats);
        Person person = new Person.Builder().setName("caller").build();
        nb.setStyle(Notification.CallStyle.forOngoingCall(person, mock(PendingIntent.class)));
        nb.setFullScreenIntent(mock(PendingIntent.class), true);
        sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, nb.build(),
                UserHandle.getUserHandleForUid(mUid), null, 0);
        r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);

        mService.addEnqueuedNotification(r);
        runnable = mService.new PostNotificationRunnable(
                r.getKey(), r.getSbn().getPackageName(), r.getUid(), SystemClock.elapsedRealtime());
        runnable.run();
        waitForIdle();

        verify(mUsageStats).registerBlocked(any());
        verify(mUsageStats, never()).registerPostedByApp(any());

        // style + managed call - bypasses block
        mService.clearNotifications();
        reset(mUsageStats);
        when(mTelecomManager.isInManagedCall()).thenReturn(true);

        mService.addEnqueuedNotification(r);
        runnable.run();
        waitForIdle();

        verify(mUsageStats, never()).registerBlocked(any());
        verify(mUsageStats).registerPostedByApp(any());

        // style + self managed call - bypasses block
        mService.clearNotifications();
        reset(mUsageStats);
        when(mTelecomManager.isInSelfManagedCall(r.getSbn().getPackageName(), r.getUser()))
                .thenReturn(true);

        mService.addEnqueuedNotification(r);
        runnable.run();
        waitForIdle();

        verify(mUsageStats, never()).registerBlocked(any());
        verify(mUsageStats).registerPostedByApp(any());

        // set telecom manager to null - notifications should be blocked
        // but post notifications runnable should not crash
        mService.clearNotifications();
        reset(mUsageStats);
        mService.setTelecomManager(null);

        mService.addEnqueuedNotification(r);
        runnable.run();
        waitForIdle();

        verify(mUsageStats).registerBlocked(any());
        verify(mUsageStats, never()).registerPostedByApp(any());

        // set FEATURE_TELECOM to false - notifications should be blocked
        // but post notifications runnable should not crash
        mService.setTelecomManager(mTelecomManager);
        when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(false);
        reset(mUsageStats);
        mService.setTelecomManager(null);

        mService.addEnqueuedNotification(r);
        runnable.run();
        waitForIdle();

        verify(mUsageStats).registerBlocked(any());
        verify(mUsageStats, never()).registerPostedByApp(any());
    }

    @Test