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

Commit 24859057 authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Fix setPrivateNotificationsAllowed

1) Add an on-changed broadcast so the value takes effect immediately
2) initialize NotificationLockscreenUserManagerImpl earlier, before its
dependencies need it
3) Make the behavior match the name - it should redact notifications,
not hide them

Also made some small changes in NotificationManagerServiceTest to fix
test failures on -eng builds.

Test: NotificationLockscreenUserManagerTest
Test: NotificationManagerServiceTest
Test: view notification history
Test: test app that calls setPrivateNotificationsAllowed
Flag: aconfig android.app.keyguard_private_notifications
Bug: 309920145

Change-Id: If73c2cbf02c234261bbc84cc02e7ba6a5187be2e
parent 37727f65
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -240,6 +240,23 @@ public class StatusBarManager {
    /** @hide */
    public static final int CAMERA_LAUNCH_SOURCE_QUICK_AFFORDANCE = 3;

    /**
     * Broadcast action: sent to apps that hold the status bar permission when
     * KeyguardManager#setPrivateNotificationsAllowed() is changed.
     *
     * Extras: #EXTRA_KM_PRIVATE_NOTIFS_ALLOWED
     * @hide
     */
    public static final String ACTION_KEYGUARD_PRIVATE_NOTIFICATIONS_CHANGED
            = "android.app.action.KEYGUARD_PRIVATE_NOTIFICATIONS_CHANGED";

    /**
     * Boolean, the latest value of KeyguardManager#getPrivateNotificationsAllowed()
     * @hide
     */
    public static final String EXTRA_KM_PRIVATE_NOTIFS_ALLOWED
            = "android.app.extra.KM_PRIVATE_NOTIFS_ALLOWED";

    /**
     * Session flag for {@link #registerSessionListener} indicating the listener
     * is interested in sessions on the keygaurd.
+7 −0
Original line number Diff line number Diff line
@@ -36,3 +36,10 @@ flag {
  description: "Guards the security fix that ensures all URIs in intents and Person.java are valid"
  bug: "281044385"
}

flag {
  name: "keyguard_private_notifications"
  namespace: "systemui"
  description: "Fixes the behavior of KeyguardManager#setPrivateNotificationsAllowed()"
  bug: "309920145"
}
+1 −0
Original line number Diff line number Diff line
@@ -578,6 +578,7 @@
    <protected-broadcast android:name="com.android.settings.network.SWITCH_TO_SUBSCRIPTION" />
    <protected-broadcast android:name="com.android.settings.wifi.action.NETWORK_REQUEST" />

    <protected-broadcast android:name="android.app.action.KEYGUARD_PRIVATE_NOTIFICATIONS_CHANGED" />
    <protected-broadcast android:name="NotificationManagerService.TIMEOUT" />
    <protected-broadcast android:name="NotificationHistoryDatabase.CLEANUP" />
    <protected-broadcast android:name="ScheduleConditionProvider.EVALUATE" />
+76 −11
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
package com.android.systemui.statusbar;

import static android.app.StatusBarManager.ACTION_KEYGUARD_PRIVATE_NOTIFICATIONS_CHANGED;
import static android.app.StatusBarManager.EXTRA_KM_PRIVATE_NOTIFS_ALLOWED;
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS;
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;
@@ -22,6 +24,7 @@ import static android.os.UserHandle.USER_ALL;
import static android.os.UserHandle.USER_NULL;
import static android.provider.Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS;
import static android.provider.Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS;
import static android.app.Flags.keyguardPrivateNotifications;
import static android.os.Flags.allowPrivateProfile;

import static com.android.systemui.DejankUtils.whitelistIpcs;
@@ -47,7 +50,6 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;

@@ -149,6 +151,25 @@ public class NotificationLockscreenUserManagerImpl implements
            new ListenerSet<>();
    private final Collection<Uri> mLockScreenUris = new ArrayList<>();

    protected final BroadcastReceiver mKeyguardReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();

            if (ACTION_KEYGUARD_PRIVATE_NOTIFICATIONS_CHANGED.equals(action)) {
                if (mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
                    mKeyguardAllowingNotifications =
                            intent.getBooleanExtra(EXTRA_KM_PRIVATE_NOTIFS_ALLOWED, false);
                    if (mCurrentUserId == getSendingUserId()) {
                        boolean changed = updateLockscreenNotificationSetting();
                        if (changed) {
                            notifyNotificationStateChanged();
                        }
                    }
                }
            }
        }
    };

    protected final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() {
        @Override
@@ -321,11 +342,21 @@ public class NotificationLockscreenUserManagerImpl implements
        mLockScreenUris.add(SHOW_PRIVATE_LOCKSCREEN);

        dumpManager.registerDumpable(this);

        if (keyguardPrivateNotifications()) {
            init();
        }
    }

    public void setUpWithPresenter(NotificationPresenter presenter) {
        mPresenter = presenter;

        if (!keyguardPrivateNotifications()) {
            init();
        }
    }

    private void init() {
        mLockscreenSettingsObserver = new ContentObserver(
                mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)
                        ? mBackgroundHandler
@@ -408,6 +439,11 @@ public class NotificationLockscreenUserManagerImpl implements
                new IntentFilter(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
                mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)
                        ? mBackgroundExecutor : null, UserHandle.ALL);
        if (keyguardPrivateNotifications()) {
            mBroadcastDispatcher.registerReceiver(mKeyguardReceiver,
                    new IntentFilter(ACTION_KEYGUARD_PRIVATE_NOTIFICATIONS_CHANGED),
                    mBackgroundExecutor, UserHandle.ALL);
        }

        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_USER_ADDED);
@@ -449,6 +485,10 @@ public class NotificationLockscreenUserManagerImpl implements
        mLockscreenSettingsObserver.onChange(
                false, mLockScreenUris, 0, UserHandle.of(userId));
        updateDpcSettings(userId);

        if (keyguardPrivateNotifications()) {
            updateGlobalKeyguardSettings();
        }
    }

    public boolean shouldShowLockscreenNotifications() {
@@ -470,8 +510,12 @@ public class NotificationLockscreenUserManagerImpl implements
        boolean allowedByDpm;

        if (mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
            if (keyguardPrivateNotifications()) {
                show = mUsersUsersAllowingNotifications.get(mCurrentUserId);
            } else {
                show = mUsersUsersAllowingNotifications.get(mCurrentUserId)
                        && mKeyguardAllowingNotifications;
            }
            // If DPC never notified us about a user, that means they have no policy for the user,
            // and they allow the behavior
            allowedByDpm = mUsersDpcAllowingNotifications.get(mCurrentUserId, true);
@@ -514,9 +558,14 @@ public class NotificationLockscreenUserManagerImpl implements
                1,
                userId) != 0;
        mUsersUsersAllowingNotifications.put(userId, newAllowLockscreen);

        if (keyguardPrivateNotifications()) {
            return (newAllowLockscreen != originalAllowLockscreen);
        } else {
            boolean keyguardChanged = updateGlobalKeyguardSettings();
            return (newAllowLockscreen != originalAllowLockscreen) || keyguardChanged;
        }
    }

    @WorkerThread
    private boolean updateUserShowPrivateSettings(int userId) {
@@ -553,8 +602,14 @@ public class NotificationLockscreenUserManagerImpl implements
                Log.i(TAG, "Asking for redact notifs dpm override too early", new Throwable());
                return false;
            }
            if (keyguardPrivateNotifications()) {
                return mUsersUsersAllowingPrivateNotifications.get(userHandle)
                        && mUsersDpcAllowingPrivateNotifications.get(userHandle)
                        && mKeyguardAllowingNotifications;
            } else {
                return mUsersUsersAllowingPrivateNotifications.get(userHandle)
                        && mUsersDpcAllowingPrivateNotifications.get(userHandle);
            }
        } else {
            if (userHandle == USER_ALL) {
                return true;
@@ -641,9 +696,14 @@ public class NotificationLockscreenUserManagerImpl implements
                Log.wtf(TAG, "Asking for show notifs dpm override too early", new Throwable());
                updateDpcSettings(userHandle);
            }
            if (keyguardPrivateNotifications()) {
                return mUsersUsersAllowingNotifications.get(userHandle)
                        && mUsersDpcAllowingNotifications.get(userHandle);
            } else {
                return mUsersUsersAllowingNotifications.get(userHandle)
                        && mUsersDpcAllowingNotifications.get(userHandle)
                        && mKeyguardAllowingNotifications;
            }
        } else {
            if (isCurrentProfile(userHandle) && userHandle != mCurrentUserId) {
                return true;
@@ -682,8 +742,13 @@ public class NotificationLockscreenUserManagerImpl implements
                ent.getSbn().getNotification().visibility == Notification.VISIBILITY_PRIVATE;
        boolean userForcesRedaction = packageHasVisibilityOverride(ent.getSbn().getKey());

        if (keyguardPrivateNotifications()) {
            return !mKeyguardAllowingNotifications
                    || userForcesRedaction || notificationRequestsRedaction && isNotifRedacted;
        } else {
            return userForcesRedaction || notificationRequestsRedaction && isNotifRedacted;
        }
    }

    private boolean packageHasVisibilityOverride(String key) {
        if (mCommonNotifCollectionLazy.get() == null) {
+66 −1
Original line number Diff line number Diff line
@@ -19,9 +19,12 @@ package com.android.systemui.statusbar;
import static android.app.Notification.VISIBILITY_PRIVATE;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.VISIBILITY_NO_OVERRIDE;
import static android.app.StatusBarManager.ACTION_KEYGUARD_PRIVATE_NOTIFICATIONS_CHANGED;
import static android.app.StatusBarManager.EXTRA_KM_PRIVATE_NOTIFS_ALLOWED;
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS;
import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;
import static android.app.Flags.FLAG_KEYGUARD_PRIVATE_NOTIFICATIONS;
import static android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE;
import static android.os.UserHandle.USER_ALL;
import static android.provider.Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS;
@@ -111,7 +114,9 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {

    @Parameters(name = "{0}")
    public static List<FlagsParameterization> getParams() {
        return FlagsParameterization.allCombinationsOf(FLAG_ALLOW_PRIVATE_PROFILE);
        return FlagsParameterization.allCombinationsOf(
                FLAG_ALLOW_PRIVATE_PROFILE,
                FLAG_KEYGUARD_PRIVATE_NOTIFICATIONS);
    }

    public NotificationLockscreenUserManagerTest(FlagsParameterization flags) {
@@ -244,6 +249,19 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
            lockScreenUris, 0);
    }

    @Test
    @EnableFlags(FLAG_KEYGUARD_PRIVATE_NOTIFICATIONS)
    public void testInit() {
        when(mKeyguardManager.getPrivateNotificationsAllowed()).thenReturn(false);
        mLockscreenUserManager = new TestNotificationLockscreenUserManager(mContext);
        mLockscreenUserManager.setUpWithPresenter(mPresenter);

        mBackgroundExecutor.runAllReady();

        assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
        assertTrue(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif));
    }

    @Test
    public void testGetCurrentProfiles() {
        final SparseArray<UserInfo> expectedCurProfiles = new SparseArray<>();
@@ -578,6 +596,29 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
        verify(mDevicePolicyManager, atMost(1)).getKeyguardDisabledFeatures(any(), anyInt());
    }

    @Test
    @EnableFlags(FLAG_KEYGUARD_PRIVATE_NOTIFICATIONS)
    public void testKeyguardManager_noPrivateNotifications() {
        Mockito.clearInvocations(mDevicePolicyManager);
        // User allows notifications
        mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mCurrentUser.id);
        changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);

        BroadcastReceiver.PendingResult pr = new BroadcastReceiver.PendingResult(
                0, null, null, 0, true, false, null, mCurrentUser.id, 0);
        mLockscreenUserManager.mAllUsersReceiver.setPendingResult(pr);
        mLockscreenUserManager.mAllUsersReceiver.onReceive(mContext,
                new Intent(ACTION_KEYGUARD_PRIVATE_NOTIFICATIONS_CHANGED)
                        .putExtra(EXTRA_KM_PRIVATE_NOTIFS_ALLOWED, true));

        assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
        // it's a global field, confirm secondary too
        assertTrue(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif));
        assertFalse(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(mCurrentUser.id));
        assertFalse(mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(
                mSecondaryUser.id));
    }

    @Test
    public void testDevicePolicy_noPrivateNotifications() {
        Mockito.clearInvocations(mDevicePolicyManager);
@@ -699,6 +740,29 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
    }

    @Test
    @EnableFlags(FLAG_KEYGUARD_PRIVATE_NOTIFICATIONS)
    public void testShouldShowLockscreenNotifications_keyguardManagerNoPrivateNotifications_show() {
        // KeyguardManager does not allow notifications
        when(mKeyguardManager.getPrivateNotificationsAllowed()).thenReturn(false);
        // User allows notifications
        mSettings.putIntForUser(LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, mCurrentUser.id);
        changeSetting(LOCK_SCREEN_SHOW_NOTIFICATIONS);
        // DevicePolicy allows notifications
        when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mCurrentUser.id))
                .thenReturn(0);
        BroadcastReceiver.PendingResult pr = new BroadcastReceiver.PendingResult(
                0, null, null, 0, true, false, null, mCurrentUser.id, 0);
        mLockscreenUserManager.mKeyguardReceiver.setPendingResult(pr);
        mLockscreenUserManager.mKeyguardReceiver.onReceive(mContext,
                new Intent(ACTION_KEYGUARD_PRIVATE_NOTIFICATIONS_CHANGED)
                        .putExtra(EXTRA_KM_PRIVATE_NOTIFS_ALLOWED, false));

        assertTrue(mLockscreenUserManager.shouldShowLockscreenNotifications());
        assertTrue(mLockscreenUserManager.userAllowsNotificationsInPublic(mCurrentUser.id));
    }

    @Test
    @DisableFlags(FLAG_KEYGUARD_PRIVATE_NOTIFICATIONS)
    public void testShouldShowLockscreenNotifications_keyguardManagerNoPrivateNotifications() {
        // KeyguardManager does not allow notifications
        when(mKeyguardManager.getPrivateNotificationsAllowed()).thenReturn(false);
@@ -718,6 +782,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
    }

    @Test
    @DisableFlags(FLAG_KEYGUARD_PRIVATE_NOTIFICATIONS)
    public void testUserAllowsNotificationsInPublic_keyguardManagerNoPrivateNotifications() {
        // DevicePolicy allows notifications
        when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, mCurrentUser.id))
Loading