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

Commit 8acae83a authored by Matías Hernández's avatar Matías Hernández
Browse files

Revert "Clear notifications for packages whose permission is revoked"

This reverts commit c1de64d6.

Reason for revert: Probably responsible for performance regression, b/291437741.

Bug: 288651621
Bug: 291437741
Change-Id: Ifdfbbc37980f64f7f51cf9a4985eaa3fa2937ab8
parent b0c6ad69
Loading
Loading
Loading
Loading
+7 −28
Original line number Diff line number Diff line
@@ -2491,16 +2491,6 @@ public class NotificationManagerService extends SystemService {
        getContext().registerReceiver(mReviewNotificationPermissionsReceiver,
                ReviewNotificationPermissionsReceiver.getFilter(),
                Context.RECEIVER_NOT_EXPORTED);
        mAppOps.startWatchingMode(AppOpsManager.OP_POST_NOTIFICATION, null,
                new AppOpsManager.OnOpChangedInternalListener() {
                    @Override
                    public void onOpChanged(@NonNull String op, @NonNull String packageName,
                            int userId) {
                        mHandler.post(
                                () -> handleNotificationPermissionChange(packageName, userId));
                    }
                });
    }
    /**
@@ -3560,16 +3550,20 @@ public class NotificationManagerService extends SystemService {
            }
            mPermissionHelper.setNotificationPermission(
                    pkg, UserHandle.getUserId(uid), enabled, true);
            sendAppBlockStateChangedBroadcast(pkg, uid, !enabled);
            mMetricsLogger.write(new LogMaker(MetricsEvent.ACTION_BAN_APP_NOTES)
                    .setType(MetricsEvent.TYPE_ACTION)
                    .setPackageName(pkg)
                    .setSubtype(enabled ? 1 : 0));
            mNotificationChannelLogger.logAppNotificationsAllowed(uid, pkg, enabled);
            // Now, cancel any outstanding notifications that are part of a just-disabled app
            if (!enabled) {
                cancelAllNotificationsInt(MY_UID, MY_PID, pkg, null, 0, 0,
                        UserHandle.getUserId(uid), REASON_PACKAGE_BANNED);
            }
            // Outstanding notifications from this package will be cancelled, and the package will
            // be sent the ACTION_APP_BLOCK_STATE_CHANGED broadcast, as soon as we get the
            // callback from AppOpsManager.
            handleSavePolicyFile();
        }
        /**
@@ -5892,21 +5886,6 @@ public class NotificationManagerService extends SystemService {
        }
    };
    private void handleNotificationPermissionChange(String pkg, @UserIdInt int userId) {
        int uid = mPackageManagerInternal.getPackageUid(pkg, 0, userId);
        if (uid == INVALID_UID) {
            Log.e(TAG, String.format("No uid found for %s, %s!", pkg, userId));
            return;
        }
        boolean hasPermission = mPermissionHelper.hasPermission(uid);
        sendAppBlockStateChangedBroadcast(pkg, uid, !hasPermission);
        if (!hasPermission) {
            cancelAllNotificationsInt(MY_UID, MY_PID, pkg, /* channelId= */ null,
                    /* mustHaveFlags= */ 0, /* mustNotHaveFlags= */ 0, userId,
                    REASON_PACKAGE_BANNED);
        }
    }
    protected void checkNotificationListenerAccess() {
        if (!isCallerSystemOrPhone()) {
            getContext().enforceCallingPermission(
+42 −135
Original line number Diff line number Diff line
@@ -406,7 +406,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
    UriGrantsManagerInternal mUgmInternal;
    @Mock
    AppOpsManager mAppOpsManager;
    private AppOpsManager.OnOpChangedListener mOnPermissionChangeListener;
    @Mock
    private TestableNotificationManagerService.NotificationAssistantAccessGrantedCallback
            mNotificationAssistantAccessGrantedCallback;
@@ -606,12 +605,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
        tr.addOverride(com.android.internal.R.string.config_defaultSearchSelectorPackageName,
                SEARCH_SELECTOR_PKG);
        doAnswer(invocation -> {
            mOnPermissionChangeListener = invocation.getArgument(2);
            return null;
        }).when(mAppOpsManager).startWatchingMode(eq(AppOpsManager.OP_POST_NOTIFICATION), any(),
                any());
        mWorkerHandler = spy(mService.new WorkerHandler(mTestableLooper.getLooper()));
        mService.init(mWorkerHandler, mRankingHandler, mPackageManager, mPackageManagerClient,
                mockLightsManager, mListeners, mAssistants, mConditionProviders, mCompanionMgr,
@@ -3223,6 +3216,48 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                anyBoolean(), anyBoolean());
    }
    @Test
    public void testUpdateAppNotifyCreatorBlock() throws Exception {
        when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
        mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
        Thread.sleep(500);
        waitForIdle();
        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
        verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
        assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
                captor.getValue().getAction());
        assertEquals(PKG, captor.getValue().getPackage());
        assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
    }
    @Test
    public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception {
        when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
        mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
        verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
    }
    @Test
    public void testUpdateAppNotifyCreatorUnblock() throws Exception {
        when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
        mBinderService.setNotificationsEnabledForPackage(PKG, mUid, true);
        Thread.sleep(500);
        waitForIdle();
        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
        verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
        assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
                captor.getValue().getAction());
        assertEquals(PKG, captor.getValue().getPackage());
        assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
    }
    @Test
    public void testUpdateChannelNotifyCreatorBlock() throws Exception {
        mService.setPreferencesHelper(mPreferencesHelper);
@@ -12139,134 +12174,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                any(), eq(FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER | FLAG_SERVICE_SENDER));
    }
    @Test
    public void onOpChanged_permissionRevoked_cancelsAllNotificationsFromPackage()
            throws RemoteException {
        // Have preexisting posted notifications from revoked package and other packages.
        mService.addNotification(new NotificationRecord(mContext,
                generateSbn("revoked", 1001, 1, 0), mTestNotificationChannel));
        mService.addNotification(new NotificationRecord(mContext,
                generateSbn("other", 1002, 2, 0), mTestNotificationChannel));
        // Have preexisting enqueued notifications from revoked package and other packages.
        mService.addEnqueuedNotification(new NotificationRecord(mContext,
                generateSbn("revoked", 1001, 3, 0), mTestNotificationChannel));
        mService.addEnqueuedNotification(new NotificationRecord(mContext,
                generateSbn("other", 1002, 4, 0), mTestNotificationChannel));
        assertThat(mService.mNotificationList).hasSize(2);
        assertThat(mService.mEnqueuedNotifications).hasSize(2);
        when(mPackageManagerInternal.getPackageUid("revoked", 0, 0)).thenReturn(1001);
        when(mPermissionHelper.hasPermission(eq(1001))).thenReturn(false);
        mOnPermissionChangeListener.onOpChanged(
                AppOpsManager.OPSTR_POST_NOTIFICATION, "revoked", 0);
        waitForIdle();
        assertThat(mService.mNotificationList).hasSize(1);
        assertThat(mService.mNotificationList.get(0).getSbn().getPackageName()).isEqualTo("other");
        assertThat(mService.mEnqueuedNotifications).hasSize(1);
        assertThat(mService.mEnqueuedNotifications.get(0).getSbn().getPackageName()).isEqualTo(
                "other");
    }
    @Test
    public void onOpChanged_permissionStillGranted_notificationsAreNotAffected()
            throws RemoteException {
        // NOTE: This combination (receiving the onOpChanged broadcast for a package, the permission
        // being now granted, AND having previously posted notifications from said package) should
        // never happen (if we trust the broadcasts are correct). So this test is for a what-if
        // scenario, to verify we still handle it reasonably.
        // Have preexisting posted notifications from specific package and other packages.
        mService.addNotification(new NotificationRecord(mContext,
                generateSbn("granted", 1001, 1, 0), mTestNotificationChannel));
        mService.addNotification(new NotificationRecord(mContext,
                generateSbn("other", 1002, 2, 0), mTestNotificationChannel));
        // Have preexisting enqueued notifications from specific package and other packages.
        mService.addEnqueuedNotification(new NotificationRecord(mContext,
                generateSbn("granted", 1001, 3, 0), mTestNotificationChannel));
        mService.addEnqueuedNotification(new NotificationRecord(mContext,
                generateSbn("other", 1002, 4, 0), mTestNotificationChannel));
        assertThat(mService.mNotificationList).hasSize(2);
        assertThat(mService.mEnqueuedNotifications).hasSize(2);
        when(mPackageManagerInternal.getPackageUid("granted", 0, 0)).thenReturn(1001);
        when(mPermissionHelper.hasPermission(eq(1001))).thenReturn(true);
        mOnPermissionChangeListener.onOpChanged(
                AppOpsManager.OPSTR_POST_NOTIFICATION, "granted", 0);
        waitForIdle();
        assertThat(mService.mNotificationList).hasSize(2);
        assertThat(mService.mEnqueuedNotifications).hasSize(2);
    }
    @Test
    public void onOpChanged_permissionGranted_notifiesAppUnblocked() throws Exception {
        when(mPackageManagerInternal.getPackageUid(PKG, 0, 0)).thenReturn(1001);
        when(mPermissionHelper.hasPermission(eq(1001))).thenReturn(true);
        mOnPermissionChangeListener.onOpChanged(
                AppOpsManager.OPSTR_POST_NOTIFICATION, PKG, 0);
        waitForIdle();
        mTestableLooper.moveTimeForward(500);
        waitForIdle();
        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
        verify(mContext).sendBroadcastAsUser(captor.capture(), any(), eq(null));
        assertThat(captor.getValue().getAction()).isEqualTo(
                NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED);
        assertThat(captor.getValue().getPackage()).isEqualTo(PKG);
        assertThat(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true)).isFalse();
    }
    @Test
    public void onOpChanged_permissionRevoked_notifiesAppBlocked() throws Exception {
        when(mPackageManagerInternal.getPackageUid(PKG, 0, 0)).thenReturn(1001);
        when(mPermissionHelper.hasPermission(eq(1001))).thenReturn(false);
        mOnPermissionChangeListener.onOpChanged(
                AppOpsManager.OPSTR_POST_NOTIFICATION, PKG, 0);
        waitForIdle();
        mTestableLooper.moveTimeForward(500);
        waitForIdle();
        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
        verify(mContext).sendBroadcastAsUser(captor.capture(), any(), eq(null));
        assertThat(captor.getValue().getAction()).isEqualTo(
                NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED);
        assertThat(captor.getValue().getPackage()).isEqualTo(PKG);
        assertThat(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false)).isTrue();
    }
    @Test
    public void setNotificationsEnabledForPackage_disabling_clearsNotifications() throws Exception {
        mService.addNotification(new NotificationRecord(mContext,
                generateSbn("package", 1001, 1, 0), mTestNotificationChannel));
        assertThat(mService.mNotificationList).hasSize(1);
        when(mPackageManagerInternal.getPackageUid("package", 0, 0)).thenReturn(1001);
        when(mPermissionHelper.hasRequestedPermission(any(), eq("package"), anyInt())).thenReturn(
                true);
        // Start with granted permission and simulate effect of revoking it.
        when(mPermissionHelper.hasPermission(1001)).thenReturn(true);
        doAnswer(invocation -> {
            when(mPermissionHelper.hasPermission(1001)).thenReturn(false);
            mOnPermissionChangeListener.onOpChanged(
                    AppOpsManager.OPSTR_POST_NOTIFICATION, "package", 0);
            return null;
        }).when(mPermissionHelper).setNotificationPermission("package", 0, false, true);
        mBinderService.setNotificationsEnabledForPackage("package", 1001, false);
        waitForIdle();
        assertThat(mService.mNotificationList).hasSize(0);
        mTestableLooper.moveTimeForward(500);
        waitForIdle();
        verify(mContext).sendBroadcastAsUser(any(), eq(UserHandle.of(0)), eq(null));
    }
    private static <T extends Parcelable> T parcelAndUnparcel(T source,
            Parcelable.Creator<T> creator) {
        Parcel parcel = Parcel.obtain();