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

Commit c90615fc authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Don't attach private Notification to A11yEvent when user locked" into sc-dev am: 1b1df331

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15067464

Change-Id: I7589dbd803b815b9b6235ab29267299b2f3b0c9b
parents 6a9355f3 1b1df331
Loading
Loading
Loading
Loading
+28 −7
Original line number Original line Diff line number Diff line
@@ -140,6 +140,7 @@ import android.app.INotificationManager;
import android.app.ITransientNotification;
import android.app.ITransientNotification;
import android.app.ITransientNotificationCallback;
import android.app.ITransientNotificationCallback;
import android.app.IUriGrantsManager;
import android.app.IUriGrantsManager;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationChannelGroup;
@@ -549,6 +550,8 @@ public class NotificationManagerService extends SystemService {
    // Used for rate limiting toasts by package.
    // Used for rate limiting toasts by package.
    private MultiRateLimiter mToastRateLimiter;
    private MultiRateLimiter mToastRateLimiter;


    private KeyguardManager mKeyguardManager;

    // The last key in this list owns the hardware.
    // The last key in this list owns the hardware.
    ArrayList<String> mLights = new ArrayList<>();
    ArrayList<String> mLights = new ArrayList<>();


@@ -2007,6 +2010,11 @@ public class NotificationManagerService extends SystemService {
        mAudioManager = audioMananger;
        mAudioManager = audioMananger;
    }
    }


    @VisibleForTesting
    void setKeyguardManager(KeyguardManager keyguardManager) {
        mKeyguardManager = keyguardManager;
    }

    @VisibleForTesting
    @VisibleForTesting
    ShortcutHelper getShortcutHelper() {
    ShortcutHelper getShortcutHelper() {
        return mShortcutHelper;
        return mShortcutHelper;
@@ -2653,6 +2661,7 @@ public class NotificationManagerService extends SystemService {
            mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
            mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
            mAudioManagerInternal = getLocalService(AudioManagerInternal.class);
            mAudioManagerInternal = getLocalService(AudioManagerInternal.class);
            mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
            mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
            mKeyguardManager = getContext().getSystemService(KeyguardManager.class);
            mZenModeHelper.onSystemReady();
            mZenModeHelper.onSystemReady();
            RoleObserver roleObserver = new RoleObserver(getContext(),
            RoleObserver roleObserver = new RoleObserver(getContext(),
                    getContext().getSystemService(RoleManager.class),
                    getContext().getSystemService(RoleManager.class),
@@ -7388,7 +7397,6 @@ public class NotificationManagerService extends SystemService {
        boolean beep = false;
        boolean beep = false;
        boolean blink = false;
        boolean blink = false;


        final Notification notification = record.getSbn().getNotification();
        final String key = record.getKey();
        final String key = record.getKey();


        // Should this notification make noise, vibe, or use the LED?
        // Should this notification make noise, vibe, or use the LED?
@@ -7410,7 +7418,7 @@ public class NotificationManagerService extends SystemService {
        if (!record.isUpdate
        if (!record.isUpdate
                && record.getImportance() > IMPORTANCE_MIN
                && record.getImportance() > IMPORTANCE_MIN
                && !suppressedByDnd) {
                && !suppressedByDnd) {
            sendAccessibilityEvent(notification, record.getSbn().getPackageName());
            sendAccessibilityEvent(record);
            sentAccessibilityEvent = true;
            sentAccessibilityEvent = true;
        }
        }


@@ -7433,7 +7441,7 @@ public class NotificationManagerService extends SystemService {
                boolean hasAudibleAlert = hasValidSound || hasValidVibrate;
                boolean hasAudibleAlert = hasValidSound || hasValidVibrate;
                if (hasAudibleAlert && !shouldMuteNotificationLocked(record)) {
                if (hasAudibleAlert && !shouldMuteNotificationLocked(record)) {
                    if (!sentAccessibilityEvent) {
                    if (!sentAccessibilityEvent) {
                        sendAccessibilityEvent(notification, record.getSbn().getPackageName());
                        sendAccessibilityEvent(record);
                        sentAccessibilityEvent = true;
                        sentAccessibilityEvent = true;
                    }
                    }
                    if (DBG) Slog.v(TAG, "Interrupting!");
                    if (DBG) Slog.v(TAG, "Interrupting!");
@@ -8261,17 +8269,30 @@ public class NotificationManagerService extends SystemService {
        return (x < low) ? low : ((x > high) ? high : x);
        return (x < low) ? low : ((x > high) ? high : x);
    }
    }


    void sendAccessibilityEvent(Notification notification, CharSequence packageName) {
    void sendAccessibilityEvent(NotificationRecord record) {
        if (!mAccessibilityManager.isEnabled()) {
        if (!mAccessibilityManager.isEnabled()) {
            return;
            return;
        }
        }


        AccessibilityEvent event =
        final Notification notification = record.getNotification();
        final CharSequence packageName = record.getSbn().getPackageName();
        final AccessibilityEvent event =
            AccessibilityEvent.obtain(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
            AccessibilityEvent.obtain(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
        event.setPackageName(packageName);
        event.setPackageName(packageName);
        event.setClassName(Notification.class.getName());
        event.setClassName(Notification.class.getName());
        final int visibilityOverride = record.getPackageVisibilityOverride();
        final int notifVisibility = visibilityOverride == NotificationManager.VISIBILITY_NO_OVERRIDE
                ? notification.visibility : visibilityOverride;
        final int userId = record.getUser().getIdentifier();
        final boolean needPublic = userId >= 0 && mKeyguardManager.isDeviceLocked(userId);
        if (needPublic && notifVisibility != Notification.VISIBILITY_PUBLIC) {
            // Emit the public version if we're on the lockscreen and this notification isn't
            // publicly visible.
            event.setParcelableData(notification.publicVersion);
        } else {
            event.setParcelableData(notification);
            event.setParcelableData(notification);
        CharSequence tickerText = notification.tickerText;
        }
        final CharSequence tickerText = notification.tickerText;
        if (!TextUtils.isEmpty(tickerText)) {
        if (!TextUtils.isEmpty(tickerText)) {
            event.getText().add(tickerText);
            event.getText().add(tickerText);
        }
        }
+93 −0
Original line number Original line Diff line number Diff line
@@ -48,6 +48,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.when;


import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.Notification;
import android.app.Notification.Builder;
import android.app.Notification.Builder;
import android.app.NotificationChannel;
import android.app.NotificationChannel;
@@ -111,6 +112,8 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
    NotificationUsageStats mUsageStats;
    NotificationUsageStats mUsageStats;
    @Mock
    @Mock
    IAccessibilityManager mAccessibilityService;
    IAccessibilityManager mAccessibilityService;
    @Mock
    KeyguardManager mKeyguardManager;
    NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
    NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
    private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
    private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
            1 << 30);
            1 << 30);
@@ -153,6 +156,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
        when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
        when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
        when(mUsageStats.isAlertRateLimited(any())).thenReturn(false);
        when(mUsageStats.isAlertRateLimited(any())).thenReturn(false);
        when(mVibrator.hasFrequencyControl()).thenReturn(false);
        when(mVibrator.hasFrequencyControl()).thenReturn(false);
        when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(false);


        long serviceReturnValue = IntPair.of(
        long serviceReturnValue = IntPair.of(
                AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED,
                AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED,
@@ -174,6 +178,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
        mService.setScreenOn(false);
        mService.setScreenOn(false);
        mService.setUsageStats(mUsageStats);
        mService.setUsageStats(mUsageStats);
        mService.setAccessibilityManager(accessibilityManager);
        mService.setAccessibilityManager(accessibilityManager);
        mService.setKeyguardManager(mKeyguardManager);
        mService.mScreenOn = false;
        mService.mScreenOn = false;
        mService.mInCallStateOffHook = false;
        mService.mInCallStateOffHook = false;
        mService.mNotificationPulseEnabled = true;
        mService.mNotificationPulseEnabled = true;
@@ -495,6 +500,94 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
        assertNotEquals(-1, r.getLastAudiblyAlertedMs());
        assertNotEquals(-1, r.getLastAudiblyAlertedMs());
    }
    }


    @Test
    public void testLockedPrivateA11yRedaction() throws Exception {
        NotificationRecord r = getBeepyNotification();
        r.setPackageVisibilityOverride(NotificationManager.VISIBILITY_NO_OVERRIDE);
        r.getNotification().visibility = Notification.VISIBILITY_PRIVATE;
        when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(true);
        AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class);
        when(accessibilityManager.isEnabled()).thenReturn(true);
        mService.setAccessibilityManager(accessibilityManager);

        mService.buzzBeepBlinkLocked(r);

        ArgumentCaptor<AccessibilityEvent> eventCaptor =
                ArgumentCaptor.forClass(AccessibilityEvent.class);

        verify(accessibilityManager, times(1))
                .sendAccessibilityEvent(eventCaptor.capture());

        AccessibilityEvent event = eventCaptor.getValue();
        assertEquals(r.getNotification().publicVersion, event.getParcelableData());
    }

    @Test
    public void testLockedOverridePrivateA11yRedaction() throws Exception {
        NotificationRecord r = getBeepyNotification();
        r.setPackageVisibilityOverride(Notification.VISIBILITY_PRIVATE);
        r.getNotification().visibility = Notification.VISIBILITY_PUBLIC;
        when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(true);
        AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class);
        when(accessibilityManager.isEnabled()).thenReturn(true);
        mService.setAccessibilityManager(accessibilityManager);

        mService.buzzBeepBlinkLocked(r);

        ArgumentCaptor<AccessibilityEvent> eventCaptor =
                ArgumentCaptor.forClass(AccessibilityEvent.class);

        verify(accessibilityManager, times(1))
                .sendAccessibilityEvent(eventCaptor.capture());

        AccessibilityEvent event = eventCaptor.getValue();
        assertEquals(r.getNotification().publicVersion, event.getParcelableData());
    }

    @Test
    public void testLockedPublicA11yNoRedaction() throws Exception {
        NotificationRecord r = getBeepyNotification();
        r.setPackageVisibilityOverride(NotificationManager.VISIBILITY_NO_OVERRIDE);
        r.getNotification().visibility = Notification.VISIBILITY_PUBLIC;
        when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(true);
        AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class);
        when(accessibilityManager.isEnabled()).thenReturn(true);
        mService.setAccessibilityManager(accessibilityManager);

        mService.buzzBeepBlinkLocked(r);

        ArgumentCaptor<AccessibilityEvent> eventCaptor =
                ArgumentCaptor.forClass(AccessibilityEvent.class);

        verify(accessibilityManager, times(1))
                .sendAccessibilityEvent(eventCaptor.capture());

        AccessibilityEvent event = eventCaptor.getValue();
        assertEquals(r.getNotification(), event.getParcelableData());
    }

    @Test
    public void testUnlockedPrivateA11yNoRedaction() throws Exception {
        NotificationRecord r = getBeepyNotification();
        r.setPackageVisibilityOverride(NotificationManager.VISIBILITY_NO_OVERRIDE);
        r.getNotification().visibility = Notification.VISIBILITY_PRIVATE;
        when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(false);
        AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class);
        when(accessibilityManager.isEnabled()).thenReturn(true);
        mService.setAccessibilityManager(accessibilityManager);

        mService.buzzBeepBlinkLocked(r);

        ArgumentCaptor<AccessibilityEvent> eventCaptor =
                ArgumentCaptor.forClass(AccessibilityEvent.class);

        verify(accessibilityManager, times(1))
                .sendAccessibilityEvent(eventCaptor.capture());

        AccessibilityEvent event = eventCaptor.getValue();
        assertEquals(r.getNotification(), event.getParcelableData());
    }

    @Test
    @Test
    public void testBeepInsistently() throws Exception {
    public void testBeepInsistently() throws Exception {
        NotificationRecord r = getInsistentBeepyNotification();
        NotificationRecord r = getInsistentBeepyNotification();