DO NOT MERGE Suppress notifications when device enter lockdown
This CL makes the following modifcations:
1. Add LockPatternUtils.StrongAuthTracker to monitor
the lockdown mode status of the phone.
2. Call mListeners.notifyRemovedLocked with all the
notifications in the mNotificationList when entering
the lockdown mode.
3. Call mListeners.notifyPostedLocked with all the
notifications in the mNotificationList when exiting
the lockdown mode.
4. Dismiss the function calls of notifyPostedLocked,
notifyRemovedLocked, and notifyRankingUpdateLocked
during the lockdown mode.
The CL also adds corresponding tests.
Bug: 173721373
Test: atest NotificationManagerServiceTest
Test: atest NotificationListenersTest
Test: manually verify the paired device cannot receive
notifications when the host phone is in lockdown mode.
Ignore-AOSP-First: pending fix for a security issue.
Change-Id: I7e83544863eeadf8272b6ff8a9bb8136d6466203
Merged-In: I7e83544863eeadf8272b6ff8a9bb8136d6466203
(cherry picked from commit 3cb6842a05)
This commit is contained in:
@@ -252,6 +252,7 @@ import android.util.Log;
|
|||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
import android.util.SparseBooleanArray;
|
||||||
import android.util.StatsEvent;
|
import android.util.StatsEvent;
|
||||||
import android.util.TypedXmlPullParser;
|
import android.util.TypedXmlPullParser;
|
||||||
import android.util.TypedXmlSerializer;
|
import android.util.TypedXmlSerializer;
|
||||||
@@ -284,6 +285,7 @@ import com.android.internal.util.DumpUtils;
|
|||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
import com.android.internal.util.XmlUtils;
|
import com.android.internal.util.XmlUtils;
|
||||||
import com.android.internal.util.function.TriPredicate;
|
import com.android.internal.util.function.TriPredicate;
|
||||||
|
import com.android.internal.widget.LockPatternUtils;
|
||||||
import com.android.server.DeviceIdleInternal;
|
import com.android.server.DeviceIdleInternal;
|
||||||
import com.android.server.EventLogTags;
|
import com.android.server.EventLogTags;
|
||||||
import com.android.server.IoThread;
|
import com.android.server.IoThread;
|
||||||
@@ -1923,6 +1925,54 @@ public class NotificationManagerService extends SystemService {
|
|||||||
private SettingsObserver mSettingsObserver;
|
private SettingsObserver mSettingsObserver;
|
||||||
protected ZenModeHelper mZenModeHelper;
|
protected ZenModeHelper mZenModeHelper;
|
||||||
|
|
||||||
|
protected class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker {
|
||||||
|
|
||||||
|
SparseBooleanArray mUserInLockDownMode = new SparseBooleanArray();
|
||||||
|
boolean mIsInLockDownMode = false;
|
||||||
|
|
||||||
|
StrongAuthTracker(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean containsFlag(int haystack, int needle) {
|
||||||
|
return (haystack & needle) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInLockDownMode() {
|
||||||
|
return mIsInLockDownMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void onStrongAuthRequiredChanged(int userId) {
|
||||||
|
boolean userInLockDownModeNext = containsFlag(getStrongAuthForUser(userId),
|
||||||
|
STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
|
||||||
|
mUserInLockDownMode.put(userId, userInLockDownModeNext);
|
||||||
|
boolean isInLockDownModeNext = mUserInLockDownMode.indexOfValue(true) != -1;
|
||||||
|
|
||||||
|
if (mIsInLockDownMode == isInLockDownModeNext) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInLockDownModeNext) {
|
||||||
|
cancelNotificationsWhenEnterLockDownMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the mIsInLockDownMode is true, both notifyPostedLocked and
|
||||||
|
// notifyRemovedLocked will be dismissed. So we shall call
|
||||||
|
// cancelNotificationsWhenEnterLockDownMode before we set mIsInLockDownMode
|
||||||
|
// as true and call postNotificationsWhenExitLockDownMode after we set
|
||||||
|
// mIsInLockDownMode as false.
|
||||||
|
mIsInLockDownMode = isInLockDownModeNext;
|
||||||
|
|
||||||
|
if (!isInLockDownModeNext) {
|
||||||
|
postNotificationsWhenExitLockDownMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private LockPatternUtils mLockPatternUtils;
|
||||||
|
private StrongAuthTracker mStrongAuthTracker;
|
||||||
|
|
||||||
public NotificationManagerService(Context context) {
|
public NotificationManagerService(Context context) {
|
||||||
this(context,
|
this(context,
|
||||||
new NotificationRecordLoggerImpl(),
|
new NotificationRecordLoggerImpl(),
|
||||||
@@ -1951,6 +2001,11 @@ public class NotificationManagerService extends SystemService {
|
|||||||
mAudioManager = audioMananger;
|
mAudioManager = audioMananger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void setStrongAuthTracker(StrongAuthTracker strongAuthTracker) {
|
||||||
|
mStrongAuthTracker = strongAuthTracker;
|
||||||
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void setKeyguardManager(KeyguardManager keyguardManager) {
|
void setKeyguardManager(KeyguardManager keyguardManager) {
|
||||||
mKeyguardManager = keyguardManager;
|
mKeyguardManager = keyguardManager;
|
||||||
@@ -2145,6 +2200,8 @@ public class NotificationManagerService extends SystemService {
|
|||||||
mPlatformCompat = IPlatformCompat.Stub.asInterface(
|
mPlatformCompat = IPlatformCompat.Stub.asInterface(
|
||||||
ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
|
ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
|
||||||
|
|
||||||
|
mLockPatternUtils = new LockPatternUtils(getContext());
|
||||||
|
mStrongAuthTracker = new StrongAuthTracker(getContext());
|
||||||
mUiHandler = new Handler(UiThread.get().getLooper());
|
mUiHandler = new Handler(UiThread.get().getLooper());
|
||||||
String[] extractorNames;
|
String[] extractorNames;
|
||||||
try {
|
try {
|
||||||
@@ -2641,6 +2698,7 @@ public class NotificationManagerService extends SystemService {
|
|||||||
bubbsExtractor.setShortcutHelper(mShortcutHelper);
|
bubbsExtractor.setShortcutHelper(mShortcutHelper);
|
||||||
}
|
}
|
||||||
registerNotificationPreferencesPullers();
|
registerNotificationPreferencesPullers();
|
||||||
|
mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker);
|
||||||
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
|
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
|
||||||
// This observer will force an update when observe is called, causing us to
|
// This observer will force an update when observe is called, causing us to
|
||||||
// bind to listener services.
|
// bind to listener services.
|
||||||
@@ -9537,6 +9595,29 @@ public class NotificationManagerService extends SystemService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void cancelNotificationsWhenEnterLockDownMode() {
|
||||||
|
synchronized (mNotificationLock) {
|
||||||
|
int numNotifications = mNotificationList.size();
|
||||||
|
for (int i = 0; i < numNotifications; i++) {
|
||||||
|
NotificationRecord rec = mNotificationList.get(i);
|
||||||
|
mListeners.notifyRemovedLocked(rec, REASON_CANCEL_ALL,
|
||||||
|
rec.getStats());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void postNotificationsWhenExitLockDownMode() {
|
||||||
|
synchronized (mNotificationLock) {
|
||||||
|
int numNotifications = mNotificationList.size();
|
||||||
|
for (int i = 0; i < numNotifications; i++) {
|
||||||
|
NotificationRecord rec = mNotificationList.get(i);
|
||||||
|
mListeners.notifyPostedLocked(rec, rec);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateNotificationPulse() {
|
private void updateNotificationPulse() {
|
||||||
synchronized (mNotificationLock) {
|
synchronized (mNotificationLock) {
|
||||||
updateLightsLocked();
|
updateLightsLocked();
|
||||||
@@ -9753,6 +9834,10 @@ public class NotificationManagerService extends SystemService {
|
|||||||
rankings.toArray(new NotificationListenerService.Ranking[0]));
|
rankings.toArray(new NotificationListenerService.Ranking[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isInLockDownMode() {
|
||||||
|
return mStrongAuthTracker.isInLockDownMode();
|
||||||
|
}
|
||||||
|
|
||||||
boolean hasCompanionDevice(ManagedServiceInfo info) {
|
boolean hasCompanionDevice(ManagedServiceInfo info) {
|
||||||
if (mCompanionManager == null) {
|
if (mCompanionManager == null) {
|
||||||
mCompanionManager = getCompanionManager();
|
mCompanionManager = getCompanionManager();
|
||||||
@@ -10804,8 +10889,12 @@ public class NotificationManagerService extends SystemService {
|
|||||||
* targetting <= O_MR1
|
* targetting <= O_MR1
|
||||||
*/
|
*/
|
||||||
@GuardedBy("mNotificationLock")
|
@GuardedBy("mNotificationLock")
|
||||||
private void notifyPostedLocked(NotificationRecord r, NotificationRecord old,
|
void notifyPostedLocked(NotificationRecord r, NotificationRecord old,
|
||||||
boolean notifyAllListeners) {
|
boolean notifyAllListeners) {
|
||||||
|
if (isInLockDownMode()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Lazily initialized snapshots of the notification.
|
// Lazily initialized snapshots of the notification.
|
||||||
StatusBarNotification sbn = r.getSbn();
|
StatusBarNotification sbn = r.getSbn();
|
||||||
@@ -10908,6 +10997,10 @@ public class NotificationManagerService extends SystemService {
|
|||||||
@GuardedBy("mNotificationLock")
|
@GuardedBy("mNotificationLock")
|
||||||
public void notifyRemovedLocked(NotificationRecord r, int reason,
|
public void notifyRemovedLocked(NotificationRecord r, int reason,
|
||||||
NotificationStats notificationStats) {
|
NotificationStats notificationStats) {
|
||||||
|
if (isInLockDownMode()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final StatusBarNotification sbn = r.getSbn();
|
final StatusBarNotification sbn = r.getSbn();
|
||||||
|
|
||||||
// make a copy in case changes are made to the underlying Notification object
|
// make a copy in case changes are made to the underlying Notification object
|
||||||
@@ -10953,6 +11046,10 @@ public class NotificationManagerService extends SystemService {
|
|||||||
*/
|
*/
|
||||||
@GuardedBy("mNotificationLock")
|
@GuardedBy("mNotificationLock")
|
||||||
public void notifyRankingUpdateLocked(List<NotificationRecord> changedHiddenNotifications) {
|
public void notifyRankingUpdateLocked(List<NotificationRecord> changedHiddenNotifications) {
|
||||||
|
if (isInLockDownMode()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
boolean isHiddenRankingUpdate = changedHiddenNotifications != null
|
boolean isHiddenRankingUpdate = changedHiddenNotifications != null
|
||||||
&& changedHiddenNotifications.size() > 0;
|
&& changedHiddenNotifications.size() > 0;
|
||||||
// TODO (b/73052211): if the ranking update changed the notification type,
|
// TODO (b/73052211): if the ranking update changed the notification type,
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
<uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS" />
|
<uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS" />
|
||||||
<uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT"/>
|
<uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT"/>
|
||||||
<uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" />
|
<uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
|
||||||
|
|
||||||
<application android:debuggable="true">
|
<application android:debuggable="true">
|
||||||
<uses-library android:name="android.test.runner" />
|
<uses-library android:name="android.test.runner" />
|
||||||
|
|||||||
@@ -31,8 +31,11 @@ import static org.mockito.ArgumentMatchers.any;
|
|||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.ArgumentMatchers.nullable;
|
import static org.mockito.ArgumentMatchers.nullable;
|
||||||
|
import static org.mockito.Mockito.atLeast;
|
||||||
import static org.mockito.Mockito.doNothing;
|
import static org.mockito.Mockito.doNothing;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.reset;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@@ -42,18 +45,16 @@ import android.app.Notification;
|
|||||||
import android.app.NotificationChannel;
|
import android.app.NotificationChannel;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.pm.IPackageManager;
|
import android.content.pm.IPackageManager;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ServiceInfo;
|
import android.content.pm.ServiceInfo;
|
||||||
import android.content.pm.VersionedPackage;
|
import android.content.pm.VersionedPackage;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
|
||||||
import android.os.IInterface;
|
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.service.notification.NotificationListenerFilter;
|
import android.service.notification.NotificationListenerFilter;
|
||||||
import android.service.notification.NotificationListenerService;
|
import android.service.notification.NotificationListenerService;
|
||||||
import android.service.notification.NotificationRankingUpdate;
|
import android.service.notification.NotificationRankingUpdate;
|
||||||
|
import android.service.notification.NotificationStats;
|
||||||
import android.service.notification.StatusBarNotification;
|
import android.service.notification.StatusBarNotification;
|
||||||
import android.testing.TestableContext;
|
import android.testing.TestableContext;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
@@ -70,6 +71,7 @@ import org.junit.Before;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.mockito.internal.util.reflection.FieldSetter;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
@@ -430,4 +432,66 @@ public class NotificationListenersTest extends UiServiceTestCase {
|
|||||||
verify(mPmi).grantImplicitAccess(sbn.getUserId(), null, UserHandle.getAppId(33),
|
verify(mPmi).grantImplicitAccess(sbn.getUserId(), null, UserHandle.getAppId(33),
|
||||||
sbn.getUid(), false, false);
|
sbn.getUid(), false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNotifyPostedLockedInLockdownMode() {
|
||||||
|
NotificationRecord r = mock(NotificationRecord.class);
|
||||||
|
NotificationRecord old = mock(NotificationRecord.class);
|
||||||
|
|
||||||
|
// before the lockdown mode
|
||||||
|
when(mNm.isInLockDownMode()).thenReturn(false);
|
||||||
|
mListeners.notifyPostedLocked(r, old, true);
|
||||||
|
mListeners.notifyPostedLocked(r, old, false);
|
||||||
|
verify(r, atLeast(2)).getSbn();
|
||||||
|
|
||||||
|
// in the lockdown mode
|
||||||
|
reset(r);
|
||||||
|
reset(old);
|
||||||
|
when(mNm.isInLockDownMode()).thenReturn(true);
|
||||||
|
mListeners.notifyPostedLocked(r, old, true);
|
||||||
|
mListeners.notifyPostedLocked(r, old, false);
|
||||||
|
verify(r, never()).getSbn();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testnotifyRankingUpdateLockedInLockdownMode() {
|
||||||
|
List chn = mock(List.class);
|
||||||
|
|
||||||
|
// before the lockdown mode
|
||||||
|
when(mNm.isInLockDownMode()).thenReturn(false);
|
||||||
|
mListeners.notifyRankingUpdateLocked(chn);
|
||||||
|
verify(chn, atLeast(1)).size();
|
||||||
|
|
||||||
|
// in the lockdown mode
|
||||||
|
reset(chn);
|
||||||
|
when(mNm.isInLockDownMode()).thenReturn(true);
|
||||||
|
mListeners.notifyRankingUpdateLocked(chn);
|
||||||
|
verify(chn, never()).size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNotifyRemovedLockedInLockdownMode() throws NoSuchFieldException {
|
||||||
|
NotificationRecord r = mock(NotificationRecord.class);
|
||||||
|
NotificationStats rs = mock(NotificationStats.class);
|
||||||
|
StatusBarNotification sbn = mock(StatusBarNotification.class);
|
||||||
|
FieldSetter.setField(mNm,
|
||||||
|
NotificationManagerService.class.getDeclaredField("mHandler"),
|
||||||
|
mock(NotificationManagerService.WorkerHandler.class));
|
||||||
|
|
||||||
|
// before the lockdown mode
|
||||||
|
when(mNm.isInLockDownMode()).thenReturn(false);
|
||||||
|
when(r.getSbn()).thenReturn(sbn);
|
||||||
|
mListeners.notifyRemovedLocked(r, 0, rs);
|
||||||
|
mListeners.notifyRemovedLocked(r, 0, rs);
|
||||||
|
verify(r, atLeast(2)).getSbn();
|
||||||
|
|
||||||
|
// in the lockdown mode
|
||||||
|
reset(r);
|
||||||
|
reset(rs);
|
||||||
|
when(mNm.isInLockDownMode()).thenReturn(true);
|
||||||
|
when(r.getSbn()).thenReturn(sbn);
|
||||||
|
mListeners.notifyRemovedLocked(r, 0, rs);
|
||||||
|
mListeners.notifyRemovedLocked(r, 0, rs);
|
||||||
|
verify(r, never()).getSbn();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,10 +63,13 @@ import static android.service.notification.Adjustment.KEY_USER_SENTIMENT;
|
|||||||
import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING;
|
import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING;
|
||||||
import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_CONVERSATIONS;
|
import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_CONVERSATIONS;
|
||||||
import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING;
|
import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING;
|
||||||
|
import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL;
|
||||||
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
|
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
|
||||||
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
|
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
|
||||||
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
|
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
|
||||||
|
|
||||||
|
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static junit.framework.Assert.assertEquals;
|
import static junit.framework.Assert.assertEquals;
|
||||||
@@ -352,6 +355,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
|
|||||||
MultiRateLimiter mToastRateLimiter;
|
MultiRateLimiter mToastRateLimiter;
|
||||||
BroadcastReceiver mPackageIntentReceiver;
|
BroadcastReceiver mPackageIntentReceiver;
|
||||||
NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
|
NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
|
||||||
|
TestableNotificationManagerService.StrongAuthTrackerFake mStrongAuthTracker;
|
||||||
private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
|
private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
|
||||||
1 << 30);
|
1 << 30);
|
||||||
@Mock
|
@Mock
|
||||||
@@ -508,6 +512,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
|
|||||||
|
|
||||||
mService.setAudioManager(mAudioManager);
|
mService.setAudioManager(mAudioManager);
|
||||||
|
|
||||||
|
mStrongAuthTracker = mService.new StrongAuthTrackerFake(mContext);
|
||||||
|
mService.setStrongAuthTracker(mStrongAuthTracker);
|
||||||
|
|
||||||
mShortcutHelper = mService.getShortcutHelper();
|
mShortcutHelper = mService.getShortcutHelper();
|
||||||
mShortcutHelper.setLauncherApps(mLauncherApps);
|
mShortcutHelper.setLauncherApps(mLauncherApps);
|
||||||
mShortcutHelper.setShortcutServiceInternal(mShortcutServiceInternal);
|
mShortcutHelper.setShortcutServiceInternal(mShortcutServiceInternal);
|
||||||
@@ -9247,4 +9254,44 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
|
|||||||
// make sure the summary was removed and not re-posted
|
// make sure the summary was removed and not re-posted
|
||||||
assertThat(mService.getNotificationRecordCount()).isEqualTo(0);
|
assertThat(mService.getNotificationRecordCount()).isEqualTo(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStrongAuthTracker_isInLockDownMode() {
|
||||||
|
mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
|
||||||
|
STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
|
||||||
|
mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
|
||||||
|
assertTrue(mStrongAuthTracker.isInLockDownMode());
|
||||||
|
mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0);
|
||||||
|
mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
|
||||||
|
assertFalse(mStrongAuthTracker.isInLockDownMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCancelAndPostNotificationsWhenEnterAndExitLockDownMode() {
|
||||||
|
// post 2 notifications from 2 packages
|
||||||
|
NotificationRecord pkgA = new NotificationRecord(mContext,
|
||||||
|
generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
|
||||||
|
mService.addNotification(pkgA);
|
||||||
|
NotificationRecord pkgB = new NotificationRecord(mContext,
|
||||||
|
generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
|
||||||
|
mService.addNotification(pkgB);
|
||||||
|
|
||||||
|
// when entering the lockdown mode, cancel the 2 notifications.
|
||||||
|
mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
|
||||||
|
STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
|
||||||
|
mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
|
||||||
|
assertTrue(mStrongAuthTracker.isInLockDownMode());
|
||||||
|
|
||||||
|
// the notifyRemovedLocked function is called twice due to REASON_CANCEL_ALL.
|
||||||
|
ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class);
|
||||||
|
verify(mListeners, times(2)).notifyRemovedLocked(any(), captor.capture(), any());
|
||||||
|
assertEquals(REASON_CANCEL_ALL, captor.getValue().intValue());
|
||||||
|
|
||||||
|
// exit lockdown mode.
|
||||||
|
mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0);
|
||||||
|
mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
|
||||||
|
|
||||||
|
// the notifyPostedLocked function is called twice.
|
||||||
|
verify(mListeners, times(2)).notifyPostedLocked(any(), any());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,4 +113,20 @@ public class TestableNotificationManagerService extends NotificationManagerServi
|
|||||||
protected void doChannelWarningToast(int uid, CharSequence toastText) {
|
protected void doChannelWarningToast(int uid, CharSequence toastText) {
|
||||||
mChannelToastsSent.add(uid);
|
mChannelToastsSent.add(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class StrongAuthTrackerFake extends NotificationManagerService.StrongAuthTracker {
|
||||||
|
private int mGetStrongAuthForUserReturnValue = 0;
|
||||||
|
StrongAuthTrackerFake(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGetStrongAuthForUserReturnValue(int val) {
|
||||||
|
mGetStrongAuthForUserReturnValue = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStrongAuthForUser(int userId) {
|
||||||
|
return mGetStrongAuthForUserReturnValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user