Merge "Don't show "Clear All" w/ redacted notifs" into tm-dev am: e6e4946731
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17183599 Change-Id: I50f048ffdded7b81eb33dea6114fba2c7b237bf2 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -29,7 +29,6 @@ import com.android.keyguard.AlphaOptimizedLinearLayout;
|
|||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.plugins.DarkIconDispatcher;
|
import com.android.systemui.plugins.DarkIconDispatcher;
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry.OnSensitivityChangedListener;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
@@ -49,6 +48,7 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout {
|
|||||||
private TextView mTextView;
|
private TextView mTextView;
|
||||||
private NotificationEntry mShowingEntry;
|
private NotificationEntry mShowingEntry;
|
||||||
private Runnable mOnDrawingRectChangedListener;
|
private Runnable mOnDrawingRectChangedListener;
|
||||||
|
private boolean mRedactSensitiveContent;
|
||||||
|
|
||||||
public HeadsUpStatusBarView(Context context) {
|
public HeadsUpStatusBarView(Context context) {
|
||||||
this(context, null);
|
this(context, null);
|
||||||
@@ -111,29 +111,28 @@ public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setEntry(NotificationEntry entry) {
|
public void setEntry(NotificationEntry entry) {
|
||||||
if (mShowingEntry != null) {
|
|
||||||
mShowingEntry.removeOnSensitivityChangedListener(mOnSensitivityChangedListener);
|
|
||||||
}
|
|
||||||
mShowingEntry = entry;
|
mShowingEntry = entry;
|
||||||
|
|
||||||
if (mShowingEntry != null) {
|
if (mShowingEntry != null) {
|
||||||
CharSequence text = entry.headsUpStatusBarText;
|
CharSequence text = entry.headsUpStatusBarText;
|
||||||
if (entry.isSensitive()) {
|
if (mRedactSensitiveContent && entry.hasSensitiveContents()) {
|
||||||
text = entry.headsUpStatusBarTextPublic;
|
text = entry.headsUpStatusBarTextPublic;
|
||||||
}
|
}
|
||||||
mTextView.setText(text);
|
mTextView.setText(text);
|
||||||
mShowingEntry.addOnSensitivityChangedListener(mOnSensitivityChangedListener);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final OnSensitivityChangedListener mOnSensitivityChangedListener = entry -> {
|
public void setRedactSensitiveContent(boolean redactSensitiveContent) {
|
||||||
if (entry != mShowingEntry) {
|
if (mRedactSensitiveContent == redactSensitiveContent) {
|
||||||
throw new IllegalStateException("Got a sensitivity change for " + entry
|
return;
|
||||||
+ " but mShowingEntry is " + mShowingEntry);
|
|
||||||
}
|
}
|
||||||
// Update the text
|
mRedactSensitiveContent = redactSensitiveContent;
|
||||||
setEntry(entry);
|
if (mShowingEntry != null && mShowingEntry.hasSensitiveContents()) {
|
||||||
};
|
mTextView.setText(
|
||||||
|
mRedactSensitiveContent
|
||||||
|
? mShowingEntry.headsUpStatusBarTextPublic
|
||||||
|
: mShowingEntry.headsUpStatusBarText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||||
|
|||||||
@@ -386,7 +386,7 @@ class LockscreenShadeTransitionController @Inject constructor(
|
|||||||
}
|
}
|
||||||
if (view is ExpandableNotificationRow) {
|
if (view is ExpandableNotificationRow) {
|
||||||
// Only drag down on sensitive views, otherwise the ExpandHelper will take this
|
// Only drag down on sensitive views, otherwise the ExpandHelper will take this
|
||||||
return view.entry.isSensitive
|
return lockScreenUserManager.notifNeedsRedactionInPublic(view.entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -552,7 +552,8 @@ class LockscreenShadeTransitionController @Inject constructor(
|
|||||||
logger.logShadeDisabledOnGoToLockedShade()
|
logger.logShadeDisabledOnGoToLockedShade()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var userId: Int = lockScreenUserManager.getCurrentUserId()
|
val currentUser = lockScreenUserManager.currentUserId
|
||||||
|
var userId: Int = currentUser
|
||||||
var entry: NotificationEntry? = null
|
var entry: NotificationEntry? = null
|
||||||
if (expandView is ExpandableNotificationRow) {
|
if (expandView is ExpandableNotificationRow) {
|
||||||
entry = expandView.entry
|
entry = expandView.entry
|
||||||
@@ -562,12 +563,18 @@ class LockscreenShadeTransitionController @Inject constructor(
|
|||||||
entry.setGroupExpansionChanging(true)
|
entry.setGroupExpansionChanging(true)
|
||||||
userId = entry.sbn.userId
|
userId = entry.sbn.userId
|
||||||
}
|
}
|
||||||
var fullShadeNeedsBouncer = (!lockScreenUserManager.userAllowsPrivateNotificationsInPublic(
|
val fullShadeNeedsBouncer = when {
|
||||||
lockScreenUserManager.getCurrentUserId()) ||
|
// No bouncer necessary if we're bypassing
|
||||||
!lockScreenUserManager.shouldShowLockscreenNotifications() ||
|
keyguardBypassController.bypassEnabled -> false
|
||||||
falsingCollector.shouldEnforceBouncer())
|
// Redacted notificationss are present, bouncer should be shown before un-redacting in
|
||||||
if (keyguardBypassController.bypassEnabled) {
|
// the full shade
|
||||||
fullShadeNeedsBouncer = false
|
lockScreenUserManager.sensitiveNotifsNeedRedactionInPublic(currentUser) -> true
|
||||||
|
// Notifications are hidden in public, bouncer should be shown before showing them in
|
||||||
|
// the full shade
|
||||||
|
!lockScreenUserManager.shouldShowLockscreenNotifications() -> true
|
||||||
|
// Bouncer is being enforced, so we need to show it
|
||||||
|
falsingCollector.shouldEnforceBouncer() -> true
|
||||||
|
else -> false
|
||||||
}
|
}
|
||||||
if (lockScreenUserManager.isLockscreenPublicMode(userId) && fullShadeNeedsBouncer) {
|
if (lockScreenUserManager.isLockscreenPublicMode(userId) && fullShadeNeedsBouncer) {
|
||||||
statusBarStateController.setLeaveOpenOnKeyguardHide(true)
|
statusBarStateController.setLeaveOpenOnKeyguardHide(true)
|
||||||
@@ -911,4 +918,4 @@ class DragDownHelper(
|
|||||||
host.getLocationOnScreen(temp2)
|
host.getLocationOnScreen(temp2)
|
||||||
return expandCallback.getChildAtRawPosition(x + temp2[0], y + temp2[1])
|
return expandCallback.getChildAtRawPosition(x + temp2[0], y + temp2[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,17 +71,22 @@ public interface NotificationLockscreenUserManager {
|
|||||||
boolean shouldHideNotifications(String key);
|
boolean shouldHideNotifications(String key);
|
||||||
boolean shouldShowOnKeyguard(NotificationEntry entry);
|
boolean shouldShowOnKeyguard(NotificationEntry entry);
|
||||||
|
|
||||||
|
void addOnNeedsRedactionInPublicChangedListener(Runnable listener);
|
||||||
|
|
||||||
|
void removeOnNeedsRedactionInPublicChangedListener(Runnable listener);
|
||||||
|
|
||||||
boolean isAnyProfilePublicMode();
|
boolean isAnyProfilePublicMode();
|
||||||
|
|
||||||
void updatePublicMode();
|
void updatePublicMode();
|
||||||
|
|
||||||
boolean needsRedaction(NotificationEntry entry);
|
/** Does this notification require redaction if it is displayed when the device is public? */
|
||||||
|
boolean notifNeedsRedactionInPublic(NotificationEntry entry);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Has the given user chosen to allow their private (full) notifications to be shown even
|
* Do all sensitive notifications belonging to the given user require redaction when they are
|
||||||
* when the lockscreen is in "public" (secure & locked) mode?
|
* displayed in public?
|
||||||
*/
|
*/
|
||||||
boolean userAllowsPrivateNotificationsInPublic(int currentUserId);
|
boolean sensitiveNotifsNeedRedactionInPublic(int userId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Has the given user chosen to allow notifications to be shown even when the lockscreen is in
|
* Has the given user chosen to allow notifications to be shown even when the lockscreen is in
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import static com.android.systemui.statusbar.notification.stack.NotificationPrio
|
|||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.KeyguardManager;
|
import android.app.KeyguardManager;
|
||||||
import android.app.Notification;
|
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.admin.DevicePolicyManager;
|
import android.app.admin.DevicePolicyManager;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
@@ -45,7 +44,6 @@ import android.util.SparseBooleanArray;
|
|||||||
import com.android.internal.statusbar.NotificationVisibility;
|
import com.android.internal.statusbar.NotificationVisibility;
|
||||||
import com.android.internal.widget.LockPatternUtils;
|
import com.android.internal.widget.LockPatternUtils;
|
||||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||||
import com.android.systemui.Dependency;
|
|
||||||
import com.android.systemui.Dumpable;
|
import com.android.systemui.Dumpable;
|
||||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||||
import com.android.systemui.dagger.SysUISingleton;
|
import com.android.systemui.dagger.SysUISingleton;
|
||||||
@@ -60,6 +58,7 @@ import com.android.systemui.statusbar.notification.collection.notifcollection.Co
|
|||||||
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
|
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
|
||||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
|
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||||
|
import com.android.systemui.util.ListenerSet;
|
||||||
import com.android.systemui.util.settings.SecureSettings;
|
import com.android.systemui.util.settings.SecureSettings;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
@@ -85,13 +84,12 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
private final DeviceProvisionedController mDeviceProvisionedController;
|
private final DeviceProvisionedController mDeviceProvisionedController;
|
||||||
private final KeyguardStateController mKeyguardStateController;
|
private final KeyguardStateController mKeyguardStateController;
|
||||||
private final SecureSettings mSecureSettings;
|
private final SecureSettings mSecureSettings;
|
||||||
|
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||||
|
private final Lazy<OverviewProxyService> mOverviewProxyService;
|
||||||
private final Object mLock = new Object();
|
private final Object mLock = new Object();
|
||||||
|
|
||||||
// Lazy
|
|
||||||
private NotificationEntryManager mEntryManager;
|
|
||||||
|
|
||||||
private final Lazy<NotificationVisibilityProvider> mVisibilityProviderLazy;
|
private final Lazy<NotificationVisibilityProvider> mVisibilityProviderLazy;
|
||||||
private final Lazy<CommonNotifCollection> mCommonNotifCollectionLazy;
|
private final Lazy<CommonNotifCollection> mCommonNotifCollectionLazy;
|
||||||
|
private final Lazy<NotificationEntryManager> mEntryManagerLazy;
|
||||||
private final DevicePolicyManager mDevicePolicyManager;
|
private final DevicePolicyManager mDevicePolicyManager;
|
||||||
private final SparseBooleanArray mLockscreenPublicMode = new SparseBooleanArray();
|
private final SparseBooleanArray mLockscreenPublicMode = new SparseBooleanArray();
|
||||||
private final SparseBooleanArray mUsersWithSeparateWorkChallenge = new SparseBooleanArray();
|
private final SparseBooleanArray mUsersWithSeparateWorkChallenge = new SparseBooleanArray();
|
||||||
@@ -103,13 +101,14 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
private final List<UserChangedListener> mListeners = new ArrayList<>();
|
private final List<UserChangedListener> mListeners = new ArrayList<>();
|
||||||
private final BroadcastDispatcher mBroadcastDispatcher;
|
private final BroadcastDispatcher mBroadcastDispatcher;
|
||||||
private final NotificationClickNotifier mClickNotifier;
|
private final NotificationClickNotifier mClickNotifier;
|
||||||
|
private final LockPatternUtils mLockPatternUtils;
|
||||||
private boolean mShowLockscreenNotifications;
|
private final List<KeyguardNotificationSuppressor> mKeyguardSuppressors = new ArrayList<>();
|
||||||
private boolean mAllowLockscreenRemoteInput;
|
protected final Context mContext;
|
||||||
private LockPatternUtils mLockPatternUtils;
|
private final Handler mMainHandler;
|
||||||
protected KeyguardManager mKeyguardManager;
|
protected final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>();
|
||||||
private int mState = StatusBarState.SHADE;
|
protected final SparseArray<UserInfo> mCurrentManagedProfiles = new SparseArray<>();
|
||||||
private List<KeyguardNotificationSuppressor> mKeyguardSuppressors = new ArrayList<>();
|
private final ListenerSet<Runnable> mOnSensitiveContentRedactionChangeListeners =
|
||||||
|
new ListenerSet<>();
|
||||||
|
|
||||||
protected final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() {
|
protected final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
@@ -120,7 +119,11 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
isCurrentProfile(getSendingUserId())) {
|
isCurrentProfile(getSendingUserId())) {
|
||||||
mUsersAllowingPrivateNotifications.clear();
|
mUsersAllowingPrivateNotifications.clear();
|
||||||
updateLockscreenNotificationSetting();
|
updateLockscreenNotificationSetting();
|
||||||
getEntryManager().updateNotifications("ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED");
|
for (Runnable listener : mOnSensitiveContentRedactionChangeListeners) {
|
||||||
|
listener.run();
|
||||||
|
}
|
||||||
|
mEntryManagerLazy.get()
|
||||||
|
.updateNotifications("ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -142,7 +145,7 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
// The filtering needs to happen before the update call below in order to
|
// The filtering needs to happen before the update call below in order to
|
||||||
// make sure
|
// make sure
|
||||||
// the presenter has the updated notifications from the new user
|
// the presenter has the updated notifications from the new user
|
||||||
getEntryManager().reapplyFilterAndSort("user switched");
|
mEntryManagerLazy.get().reapplyFilterAndSort("user switched");
|
||||||
mPresenter.onUserSwitched(mCurrentUserId);
|
mPresenter.onUserSwitched(mCurrentUserId);
|
||||||
|
|
||||||
for (UserChangedListener listener : mListeners) {
|
for (UserChangedListener listener : mListeners) {
|
||||||
@@ -156,7 +159,7 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
break;
|
break;
|
||||||
case Intent.ACTION_USER_UNLOCKED:
|
case Intent.ACTION_USER_UNLOCKED:
|
||||||
// Start the overview connection to the launcher service
|
// Start the overview connection to the launcher service
|
||||||
Dependency.get(OverviewProxyService.class).startConnectionToCurrentUser();
|
mOverviewProxyService.get().startConnectionToCurrentUser();
|
||||||
break;
|
break;
|
||||||
case NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION:
|
case NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION:
|
||||||
final IntentSender intentSender = intent.getParcelableExtra(
|
final IntentSender intentSender = intent.getParcelableExtra(
|
||||||
@@ -179,28 +182,26 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
protected final Context mContext;
|
// Late-init
|
||||||
private final Handler mMainHandler;
|
|
||||||
protected final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>();
|
|
||||||
protected final SparseArray<UserInfo> mCurrentManagedProfiles = new SparseArray<>();
|
|
||||||
|
|
||||||
protected int mCurrentUserId = 0;
|
|
||||||
protected NotificationPresenter mPresenter;
|
protected NotificationPresenter mPresenter;
|
||||||
protected ContentObserver mLockscreenSettingsObserver;
|
protected ContentObserver mLockscreenSettingsObserver;
|
||||||
protected ContentObserver mSettingsObserver;
|
protected ContentObserver mSettingsObserver;
|
||||||
private boolean mHideSilentNotificationsOnLockscreen;
|
protected KeyguardManager mKeyguardManager;
|
||||||
|
|
||||||
private NotificationEntryManager getEntryManager() {
|
protected int mCurrentUserId = 0;
|
||||||
if (mEntryManager == null) {
|
private int mState = StatusBarState.SHADE;
|
||||||
mEntryManager = Dependency.get(NotificationEntryManager.class);
|
private boolean mHideSilentNotificationsOnLockscreen;
|
||||||
}
|
private boolean mShowLockscreenNotifications;
|
||||||
return mEntryManager;
|
private boolean mAllowLockscreenRemoteInput;
|
||||||
}
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public NotificationLockscreenUserManagerImpl(Context context,
|
public NotificationLockscreenUserManagerImpl(
|
||||||
|
Context context,
|
||||||
BroadcastDispatcher broadcastDispatcher,
|
BroadcastDispatcher broadcastDispatcher,
|
||||||
DevicePolicyManager devicePolicyManager,
|
DevicePolicyManager devicePolicyManager,
|
||||||
|
KeyguardUpdateMonitor keyguardUpdateMonitor,
|
||||||
|
Lazy<NotificationEntryManager> notificationEntryManagerLazy,
|
||||||
|
Lazy<OverviewProxyService> overviewProxyServiceLazy,
|
||||||
UserManager userManager,
|
UserManager userManager,
|
||||||
Lazy<NotificationVisibilityProvider> visibilityProviderLazy,
|
Lazy<NotificationVisibilityProvider> visibilityProviderLazy,
|
||||||
Lazy<CommonNotifCollection> commonNotifCollectionLazy,
|
Lazy<CommonNotifCollection> commonNotifCollectionLazy,
|
||||||
@@ -216,9 +217,11 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
mMainHandler = mainHandler;
|
mMainHandler = mainHandler;
|
||||||
mDevicePolicyManager = devicePolicyManager;
|
mDevicePolicyManager = devicePolicyManager;
|
||||||
mUserManager = userManager;
|
mUserManager = userManager;
|
||||||
|
mOverviewProxyService = overviewProxyServiceLazy;
|
||||||
mCurrentUserId = ActivityManager.getCurrentUser();
|
mCurrentUserId = ActivityManager.getCurrentUser();
|
||||||
mVisibilityProviderLazy = visibilityProviderLazy;
|
mVisibilityProviderLazy = visibilityProviderLazy;
|
||||||
mCommonNotifCollectionLazy = commonNotifCollectionLazy;
|
mCommonNotifCollectionLazy = commonNotifCollectionLazy;
|
||||||
|
mEntryManagerLazy = notificationEntryManagerLazy;
|
||||||
mClickNotifier = clickNotifier;
|
mClickNotifier = clickNotifier;
|
||||||
statusBarStateController.addCallback(this);
|
statusBarStateController.addCallback(this);
|
||||||
mLockPatternUtils = new LockPatternUtils(context);
|
mLockPatternUtils = new LockPatternUtils(context);
|
||||||
@@ -227,10 +230,12 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
mDeviceProvisionedController = deviceProvisionedController;
|
mDeviceProvisionedController = deviceProvisionedController;
|
||||||
mSecureSettings = secureSettings;
|
mSecureSettings = secureSettings;
|
||||||
mKeyguardStateController = keyguardStateController;
|
mKeyguardStateController = keyguardStateController;
|
||||||
|
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||||
|
|
||||||
dumpManager.registerDumpable(this);
|
dumpManager.registerDumpable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setUpWithPresenter(NotificationPresenter presenter) {
|
public void setUpWithPresenter(NotificationPresenter presenter) {
|
||||||
mPresenter = presenter;
|
mPresenter = presenter;
|
||||||
|
|
||||||
@@ -243,7 +248,10 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
mUsersAllowingNotifications.clear();
|
mUsersAllowingNotifications.clear();
|
||||||
// ... and refresh all the notifications
|
// ... and refresh all the notifications
|
||||||
updateLockscreenNotificationSetting();
|
updateLockscreenNotificationSetting();
|
||||||
getEntryManager().updateNotifications("LOCK_SCREEN_SHOW_NOTIFICATIONS,"
|
for (Runnable listener : mOnSensitiveContentRedactionChangeListeners) {
|
||||||
|
listener.run();
|
||||||
|
}
|
||||||
|
mEntryManagerLazy.get().updateNotifications("LOCK_SCREEN_SHOW_NOTIFICATIONS,"
|
||||||
+ " or LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS change");
|
+ " or LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS change");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -253,7 +261,7 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
public void onChange(boolean selfChange) {
|
public void onChange(boolean selfChange) {
|
||||||
updateLockscreenNotificationSetting();
|
updateLockscreenNotificationSetting();
|
||||||
if (mDeviceProvisionedController.isDeviceProvisioned()) {
|
if (mDeviceProvisionedController.isDeviceProvisioned()) {
|
||||||
getEntryManager().updateNotifications("LOCK_SCREEN_ALLOW_REMOTE_INPUT"
|
mEntryManagerLazy.get().updateNotifications("LOCK_SCREEN_ALLOW_REMOTE_INPUT"
|
||||||
+ " or ZEN_MODE change");
|
+ " or ZEN_MODE change");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -312,14 +320,17 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
mSettingsObserver.onChange(false); // set up
|
mSettingsObserver.onChange(false); // set up
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean shouldShowLockscreenNotifications() {
|
public boolean shouldShowLockscreenNotifications() {
|
||||||
return mShowLockscreenNotifications;
|
return mShowLockscreenNotifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean shouldAllowLockscreenRemoteInput() {
|
public boolean shouldAllowLockscreenRemoteInput() {
|
||||||
return mAllowLockscreenRemoteInput;
|
return mAllowLockscreenRemoteInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isCurrentProfile(int userId) {
|
public boolean isCurrentProfile(int userId) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null;
|
return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null;
|
||||||
@@ -334,7 +345,7 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
if (userId == UserHandle.USER_ALL) {
|
if (userId == UserHandle.USER_ALL) {
|
||||||
userId = mCurrentUserId;
|
userId = mCurrentUserId;
|
||||||
}
|
}
|
||||||
boolean inLockdown = Dependency.get(KeyguardUpdateMonitor.class).isUserInLockdown(userId);
|
boolean inLockdown = mKeyguardUpdateMonitor.isUserInLockdown(userId);
|
||||||
mUsersInLockdownLatestResult.put(userId, inLockdown);
|
mUsersInLockdownLatestResult.put(userId, inLockdown);
|
||||||
return inLockdown;
|
return inLockdown;
|
||||||
}
|
}
|
||||||
@@ -343,6 +354,7 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
* Returns true if we're on a secure lockscreen and the user wants to hide notification data.
|
* Returns true if we're on a secure lockscreen and the user wants to hide notification data.
|
||||||
* If so, notifications should be hidden.
|
* If so, notifications should be hidden.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public boolean shouldHideNotifications(int userId) {
|
public boolean shouldHideNotifications(int userId) {
|
||||||
boolean hide = isLockscreenPublicMode(userId) && !userAllowsNotificationsInPublic(userId)
|
boolean hide = isLockscreenPublicMode(userId) && !userAllowsNotificationsInPublic(userId)
|
||||||
|| (userId != mCurrentUserId && shouldHideNotifications(mCurrentUserId))
|
|| (userId != mCurrentUserId && shouldHideNotifications(mCurrentUserId))
|
||||||
@@ -355,6 +367,7 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
* Returns true if we're on a secure lockscreen and the user wants to hide notifications via
|
* Returns true if we're on a secure lockscreen and the user wants to hide notifications via
|
||||||
* package-specific override.
|
* package-specific override.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public boolean shouldHideNotifications(String key) {
|
public boolean shouldHideNotifications(String key) {
|
||||||
if (mCommonNotifCollectionLazy.get() == null) {
|
if (mCommonNotifCollectionLazy.get() == null) {
|
||||||
Log.wtf(TAG, "mCommonNotifCollectionLazy was null!", new Throwable());
|
Log.wtf(TAG, "mCommonNotifCollectionLazy was null!", new Throwable());
|
||||||
@@ -365,6 +378,7 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
&& visibleEntry.getRanking().getLockscreenVisibilityOverride() == VISIBILITY_SECRET;
|
&& visibleEntry.getRanking().getLockscreenVisibilityOverride() == VISIBILITY_SECRET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean shouldShowOnKeyguard(NotificationEntry entry) {
|
public boolean shouldShowOnKeyguard(NotificationEntry entry) {
|
||||||
if (mCommonNotifCollectionLazy.get() == null) {
|
if (mCommonNotifCollectionLazy.get() == null) {
|
||||||
Log.wtf(TAG, "mCommonNotifCollectionLazy was null!", new Throwable());
|
Log.wtf(TAG, "mCommonNotifCollectionLazy was null!", new Throwable());
|
||||||
@@ -387,14 +401,6 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
return mShowLockscreenNotifications && exceedsPriorityThreshold;
|
return mShowLockscreenNotifications && exceedsPriorityThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setShowLockscreenNotifications(boolean show) {
|
|
||||||
mShowLockscreenNotifications = show;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setLockscreenAllowRemoteInput(boolean allowLockscreenRemoteInput) {
|
|
||||||
mAllowLockscreenRemoteInput = allowLockscreenRemoteInput;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void updateLockscreenNotificationSetting() {
|
protected void updateLockscreenNotificationSetting() {
|
||||||
final boolean show = mSecureSettings.getIntForUser(
|
final boolean show = mSecureSettings.getIntForUser(
|
||||||
Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
|
Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
|
||||||
@@ -408,7 +414,7 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
mHideSilentNotificationsOnLockscreen = mSecureSettings.getIntForUser(
|
mHideSilentNotificationsOnLockscreen = mSecureSettings.getIntForUser(
|
||||||
Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1, mCurrentUserId) == 0;
|
Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1, mCurrentUserId) == 0;
|
||||||
|
|
||||||
setShowLockscreenNotifications(show && allowedByDpm);
|
mShowLockscreenNotifications = show && allowedByDpm;
|
||||||
|
|
||||||
if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
|
if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
|
||||||
final boolean remoteInput = mSecureSettings.getIntForUser(
|
final boolean remoteInput = mSecureSettings.getIntForUser(
|
||||||
@@ -418,9 +424,9 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
final boolean remoteInputDpm =
|
final boolean remoteInputDpm =
|
||||||
(dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) == 0;
|
(dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) == 0;
|
||||||
|
|
||||||
setLockscreenAllowRemoteInput(remoteInput && remoteInputDpm);
|
mAllowLockscreenRemoteInput = remoteInput && remoteInputDpm;
|
||||||
} else {
|
} else {
|
||||||
setLockscreenAllowRemoteInput(false);
|
mAllowLockscreenRemoteInput = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,7 +434,7 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
* Has the given user chosen to allow their private (full) notifications to be shown even
|
* Has the given user chosen to allow their private (full) notifications to be shown even
|
||||||
* when the lockscreen is in "public" (secure & locked) mode?
|
* when the lockscreen is in "public" (secure & locked) mode?
|
||||||
*/
|
*/
|
||||||
public boolean userAllowsPrivateNotificationsInPublic(int userHandle) {
|
protected boolean userAllowsPrivateNotificationsInPublic(int userHandle) {
|
||||||
if (userHandle == UserHandle.USER_ALL) {
|
if (userHandle == UserHandle.USER_ALL) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -473,10 +479,12 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
/**
|
/**
|
||||||
* Save the current "public" (locked and secure) state of the lockscreen.
|
* Save the current "public" (locked and secure) state of the lockscreen.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void setLockscreenPublicMode(boolean publicMode, int userId) {
|
public void setLockscreenPublicMode(boolean publicMode, int userId) {
|
||||||
mLockscreenPublicMode.put(userId, publicMode);
|
mLockscreenPublicMode.put(userId, publicMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isLockscreenPublicMode(int userId) {
|
public boolean isLockscreenPublicMode(int userId) {
|
||||||
if (userId == UserHandle.USER_ALL) {
|
if (userId == UserHandle.USER_ALL) {
|
||||||
return mLockscreenPublicMode.get(mCurrentUserId, false);
|
return mLockscreenPublicMode.get(mCurrentUserId, false);
|
||||||
@@ -493,6 +501,7 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
* Has the given user chosen to allow notifications to be shown even when the lockscreen is in
|
* Has the given user chosen to allow notifications to be shown even when the lockscreen is in
|
||||||
* "public" (secure & locked) mode?
|
* "public" (secure & locked) mode?
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public boolean userAllowsNotificationsInPublic(int userHandle) {
|
public boolean userAllowsNotificationsInPublic(int userHandle) {
|
||||||
if (isCurrentProfile(userHandle) && userHandle != mCurrentUserId) {
|
if (isCurrentProfile(userHandle) && userHandle != mCurrentUserId) {
|
||||||
return true;
|
return true;
|
||||||
@@ -513,36 +522,37 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the entry needs redaction when on the lockscreen. */
|
/** @return true if the entry needs redaction when on the lockscreen. */
|
||||||
public boolean needsRedaction(NotificationEntry ent) {
|
@Override
|
||||||
|
public boolean notifNeedsRedactionInPublic(NotificationEntry ent) {
|
||||||
int userId = ent.getSbn().getUserId();
|
int userId = ent.getSbn().getUserId();
|
||||||
|
return ent.hasSensitiveContents() && sensitiveNotifsNeedRedactionInPublic(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean sensitiveNotifsNeedRedactionInPublic(int userId) {
|
||||||
boolean isCurrentUserRedactingNotifs =
|
boolean isCurrentUserRedactingNotifs =
|
||||||
!userAllowsPrivateNotificationsInPublic(mCurrentUserId);
|
!userAllowsPrivateNotificationsInPublic(mCurrentUserId);
|
||||||
|
if (userId == mCurrentUserId) {
|
||||||
|
return isCurrentUserRedactingNotifs;
|
||||||
|
}
|
||||||
|
|
||||||
boolean isNotifForManagedProfile = mCurrentManagedProfiles.contains(userId);
|
boolean isNotifForManagedProfile = mCurrentManagedProfiles.contains(userId);
|
||||||
boolean isNotifUserRedacted = !userAllowsPrivateNotificationsInPublic(userId);
|
boolean isNotifUserRedacted = !userAllowsPrivateNotificationsInPublic(userId);
|
||||||
|
|
||||||
// redact notifications if the current user is redacting notifications; however if the
|
// redact notifications if the current user is redacting notifications; however if the
|
||||||
// notification is associated with a managed profile, we rely on the managed profile
|
// notification is associated with a managed profile, we rely on the managed profile
|
||||||
// setting to determine whether to redact it
|
// setting to determine whether to redact it
|
||||||
boolean isNotifRedacted = (!isNotifForManagedProfile && isCurrentUserRedactingNotifs)
|
return (!isNotifForManagedProfile && isCurrentUserRedactingNotifs) || isNotifUserRedacted;
|
||||||
|| isNotifUserRedacted;
|
|
||||||
|
|
||||||
boolean notificationRequestsRedaction =
|
|
||||||
ent.getSbn().getNotification().visibility == Notification.VISIBILITY_PRIVATE;
|
|
||||||
boolean userForcesRedaction = packageHasVisibilityOverride(ent.getSbn().getKey());
|
|
||||||
|
|
||||||
return userForcesRedaction || notificationRequestsRedaction && isNotifRedacted;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean packageHasVisibilityOverride(String key) {
|
@Override
|
||||||
if (mCommonNotifCollectionLazy.get() == null) {
|
public void addOnNeedsRedactionInPublicChangedListener(Runnable listener) {
|
||||||
Log.wtf(TAG, "mEntryManager was null!", new Throwable());
|
mOnSensitiveContentRedactionChangeListeners.addIfAbsent(listener);
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
NotificationEntry entry = mCommonNotifCollectionLazy.get().getEntry(key);
|
@Override
|
||||||
return entry != null
|
public void removeOnNeedsRedactionInPublicChangedListener(Runnable listener) {
|
||||||
&& entry.getRanking().getLockscreenVisibilityOverride()
|
mOnSensitiveContentRedactionChangeListeners.remove(listener);
|
||||||
== Notification.VISIBILITY_PRIVATE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateCurrentProfilesCache() {
|
private void updateCurrentProfilesCache() {
|
||||||
@@ -562,12 +572,16 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
for (UserChangedListener listener : mListeners) {
|
for (UserChangedListener listener : mListeners) {
|
||||||
listener.onCurrentProfilesChanged(mCurrentProfiles);
|
listener.onCurrentProfilesChanged(mCurrentProfiles);
|
||||||
}
|
}
|
||||||
|
for (Runnable listener : mOnSensitiveContentRedactionChangeListeners) {
|
||||||
|
listener.run();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If any of the profiles are in public mode.
|
* If any of the profiles are in public mode.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public boolean isAnyProfilePublicMode() {
|
public boolean isAnyProfilePublicMode() {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) {
|
for (int i = mCurrentProfiles.size() - 1; i >= 0; i--) {
|
||||||
@@ -596,10 +610,12 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
/**
|
/**
|
||||||
* Returns the current user id. This can change if the user is switched.
|
* Returns the current user id. This can change if the user is switched.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public int getCurrentUserId() {
|
public int getCurrentUserId() {
|
||||||
return mCurrentUserId;
|
return mCurrentUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public SparseArray<UserInfo> getCurrentProfiles() {
|
public SparseArray<UserInfo> getCurrentProfiles() {
|
||||||
return mCurrentProfiles;
|
return mCurrentProfiles;
|
||||||
}
|
}
|
||||||
@@ -640,7 +656,8 @@ public class NotificationLockscreenUserManagerImpl implements
|
|||||||
setLockscreenPublicMode(isProfilePublic, userId);
|
setLockscreenPublicMode(isProfilePublic, userId);
|
||||||
mUsersWithSeparateWorkChallenge.put(userId, needsSeparateChallenge);
|
mUsersWithSeparateWorkChallenge.put(userId, needsSeparateChallenge);
|
||||||
}
|
}
|
||||||
getEntryManager().updateNotifications("NotificationLockscreenUserManager.updatePublicMode");
|
mEntryManagerLazy.get()
|
||||||
|
.updateNotifications("NotificationLockscreenUserManager.updatePublicMode");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ import com.android.wm.shell.bubbles.Bubbles;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
@@ -207,12 +208,9 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
|
|||||||
|| !mLockscreenUserManager.needsSeparateWorkChallenge(userId))) {
|
|| !mLockscreenUserManager.needsSeparateWorkChallenge(userId))) {
|
||||||
userPublic = false;
|
userPublic = false;
|
||||||
}
|
}
|
||||||
boolean needsRedaction = mLockscreenUserManager.needsRedaction(ent);
|
boolean needsRedaction = mLockscreenUserManager.notifNeedsRedactionInPublic(ent);
|
||||||
boolean sensitive = userPublic && needsRedaction;
|
boolean sensitive = userPublic && needsRedaction;
|
||||||
boolean deviceSensitive = devicePublic
|
ent.getRow().setSensitive(sensitive);
|
||||||
&& !mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(
|
|
||||||
currentUserId);
|
|
||||||
ent.setSensitive(sensitive, deviceSensitive);
|
|
||||||
ent.getRow().setNeedsRedaction(needsRedaction);
|
ent.getRow().setNeedsRedaction(needsRedaction);
|
||||||
mLowPriorityInflationHelper.recheckLowPriorityViewAndInflate(ent, ent.getRow());
|
mLowPriorityInflationHelper.recheckLowPriorityViewAndInflate(ent, ent.getRow());
|
||||||
boolean isChildInGroup = mGroupManager.isChildInGroup(ent);
|
boolean isChildInGroup = mGroupManager.isChildInGroup(ent);
|
||||||
@@ -365,6 +363,8 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
|
|||||||
boolean hasClearableAlertingNotifs = false;
|
boolean hasClearableAlertingNotifs = false;
|
||||||
boolean hasNonClearableSilentNotifs = false;
|
boolean hasNonClearableSilentNotifs = false;
|
||||||
boolean hasClearableSilentNotifs = false;
|
boolean hasClearableSilentNotifs = false;
|
||||||
|
HashSet<Integer> clearableAlertingSensitiveNotifUsers = new HashSet<>();
|
||||||
|
HashSet<Integer> clearableSilentSensitiveNotifUsers = new HashSet<>();
|
||||||
final int childCount = mListContainer.getContainerChildCount();
|
final int childCount = mListContainer.getContainerChildCount();
|
||||||
int visibleTopLevelEntries = 0;
|
int visibleTopLevelEntries = 0;
|
||||||
for (int i = 0; i < childCount; i++) {
|
for (int i = 0; i < childCount; i++) {
|
||||||
@@ -376,10 +376,11 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final ExpandableNotificationRow row = (ExpandableNotificationRow) child;
|
final ExpandableNotificationRow row = (ExpandableNotificationRow) child;
|
||||||
boolean isSilent = row.getEntry().getBucket() == BUCKET_SILENT;
|
NotificationEntry entry = row.getEntry();
|
||||||
|
boolean isSilent = entry.getBucket() == BUCKET_SILENT;
|
||||||
// NOTE: NotificationEntry.isClearable() will internally check group children to ensure
|
// NOTE: NotificationEntry.isClearable() will internally check group children to ensure
|
||||||
// the group itself definitively clearable.
|
// the group itself definitively clearable.
|
||||||
boolean isClearable = row.getEntry().isClearable();
|
boolean isClearable = entry.isClearable();
|
||||||
visibleTopLevelEntries++;
|
visibleTopLevelEntries++;
|
||||||
if (isSilent) {
|
if (isSilent) {
|
||||||
if (isClearable) {
|
if (isClearable) {
|
||||||
@@ -394,13 +395,24 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
|
|||||||
hasNonClearableAlertingNotifs = true;
|
hasNonClearableAlertingNotifs = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (isClearable && entry.hasSensitiveContents()) {
|
||||||
|
int userId = entry.getSbn().getUserId();
|
||||||
|
if (isSilent) {
|
||||||
|
clearableSilentSensitiveNotifUsers.add(userId);
|
||||||
|
} else {
|
||||||
|
clearableAlertingSensitiveNotifUsers.add(userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mStackController.setNotifStats(new NotifStats(
|
mStackController.setNotifStats(new NotifStats(
|
||||||
visibleTopLevelEntries /* numActiveNotifs */,
|
visibleTopLevelEntries /* numActiveNotifs */,
|
||||||
hasNonClearableAlertingNotifs /* hasNonClearableAlertingNotifs */,
|
hasNonClearableAlertingNotifs /* hasNonClearableAlertingNotifs */,
|
||||||
hasClearableAlertingNotifs /* hasClearableAlertingNotifs */,
|
hasClearableAlertingNotifs /* hasClearableAlertingNotifs */,
|
||||||
hasNonClearableSilentNotifs /* hasNonClearableSilentNotifs */,
|
hasNonClearableSilentNotifs /* hasNonClearableSilentNotifs */,
|
||||||
hasClearableSilentNotifs /* hasClearableSilentNotifs */
|
hasClearableSilentNotifs /* hasClearableSilentNotifs */,
|
||||||
|
clearableAlertingSensitiveNotifUsers /* clearableAlertingSensitiveNotifUsers */,
|
||||||
|
clearableSilentSensitiveNotifUsers /* clearableSilentSensitiveNotifUsers */
|
||||||
|
|
||||||
));
|
));
|
||||||
Trace.endSection();
|
Trace.endSection();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ public class DynamicPrivacyController implements KeyguardStateController.Callbac
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
boolean isDynamicPrivacyEnabled() {
|
boolean isDynamicPrivacyEnabled() {
|
||||||
return !mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(
|
return mLockscreenUserManager.sensitiveNotifsNeedRedactionInPublic(
|
||||||
mLockscreenUserManager.getCurrentUserId());
|
mLockscreenUserManager.getCurrentUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,6 +95,10 @@ public class DynamicPrivacyController implements KeyguardStateController.Callbac
|
|||||||
mListeners.add(listener);
|
mListeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeListener(Listener listener) {
|
||||||
|
mListeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the notification shade currently in a locked down mode where it's fully showing but the
|
* Is the notification shade currently in a locked down mode where it's fully showing but the
|
||||||
* contents aren't revealed yet?
|
* contents aren't revealed yet?
|
||||||
|
|||||||
@@ -169,9 +169,6 @@ public final class NotificationEntry extends ListEntry {
|
|||||||
*/
|
*/
|
||||||
private boolean hasSentReply;
|
private boolean hasSentReply;
|
||||||
|
|
||||||
private boolean mSensitive = true;
|
|
||||||
private List<OnSensitivityChangedListener> mOnSensitivityChangedListeners = new ArrayList<>();
|
|
||||||
|
|
||||||
private boolean mAutoHeadsUp;
|
private boolean mAutoHeadsUp;
|
||||||
private boolean mPulseSupressed;
|
private boolean mPulseSupressed;
|
||||||
private int mBucket = BUCKET_ALERTING;
|
private int mBucket = BUCKET_ALERTING;
|
||||||
@@ -867,33 +864,29 @@ public final class NotificationEntry extends ListEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set this notification to be sensitive.
|
* Returns the visibility of this notification on the lockscreen, taking into account both the
|
||||||
*
|
* notification's defined visibility, as well as the visibility override as determined by the
|
||||||
* @param sensitive true if the content of this notification is sensitive right now
|
* device policy.
|
||||||
* @param deviceSensitive true if the device in general is sensitive right now
|
|
||||||
*/
|
*/
|
||||||
public void setSensitive(boolean sensitive, boolean deviceSensitive) {
|
public int getLockscreenVisibility() {
|
||||||
getRow().setSensitive(sensitive, deviceSensitive);
|
int setting = mRanking.getLockscreenVisibilityOverride();
|
||||||
if (sensitive != mSensitive) {
|
if (setting == Ranking.VISIBILITY_NO_OVERRIDE) {
|
||||||
mSensitive = sensitive;
|
setting = mSbn.getNotification().visibility;
|
||||||
for (int i = 0; i < mOnSensitivityChangedListeners.size(); i++) {
|
|
||||||
mOnSensitivityChangedListeners.get(i).onSensitivityChanged(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return setting;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSensitive() {
|
/**
|
||||||
return mSensitive;
|
* Does this notification contain sensitive content? If the user's settings specify, then this
|
||||||
}
|
* content would need to be redacted when the device this public.
|
||||||
|
*
|
||||||
/** Add a listener to be notified when the entry's sensitivity changes. */
|
* NOTE: If the notification's visibility setting is VISIBILITY_SECRET, then this will return
|
||||||
public void addOnSensitivityChangedListener(OnSensitivityChangedListener listener) {
|
* false; SECRET notifications are omitted entirely when the device is public, so effectively
|
||||||
mOnSensitivityChangedListeners.add(listener);
|
* the contents of the notification are not sensitive whenever the notification is actually
|
||||||
}
|
* visible.
|
||||||
|
*/
|
||||||
/** Remove a listener that was registered above. */
|
public boolean hasSensitiveContents() {
|
||||||
public void removeOnSensitivityChangedListener(OnSensitivityChangedListener listener) {
|
return getLockscreenVisibility() == Notification.VISIBILITY_PRIVATE;
|
||||||
mOnSensitivityChangedListeners.remove(listener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPulseSuppressed() {
|
public boolean isPulseSuppressed() {
|
||||||
@@ -954,12 +947,6 @@ public final class NotificationEntry extends ListEntry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Listener interface for {@link #addOnSensitivityChangedListener} */
|
|
||||||
public interface OnSensitivityChangedListener {
|
|
||||||
/** Called when the sensitivity changes */
|
|
||||||
void onSensitivityChanged(@NonNull NotificationEntry entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @see #getDismissState() */
|
/** @see #getDismissState() */
|
||||||
public enum DismissState {
|
public enum DismissState {
|
||||||
/** User has not dismissed this notif or its parent */
|
/** User has not dismissed this notif or its parent */
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ class NotifCoordinatorsImpl @Inject constructor(
|
|||||||
smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator,
|
smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator,
|
||||||
viewConfigCoordinator: ViewConfigCoordinator,
|
viewConfigCoordinator: ViewConfigCoordinator,
|
||||||
visualStabilityCoordinator: VisualStabilityCoordinator,
|
visualStabilityCoordinator: VisualStabilityCoordinator,
|
||||||
sensitiveContentCoordinator: SensitiveContentCoordinator,
|
|
||||||
activityLaunchAnimCoordinator: ActivityLaunchAnimCoordinator
|
activityLaunchAnimCoordinator: ActivityLaunchAnimCoordinator
|
||||||
) : NotifCoordinators {
|
) : NotifCoordinators {
|
||||||
|
|
||||||
@@ -94,7 +93,6 @@ class NotifCoordinatorsImpl @Inject constructor(
|
|||||||
mCoordinators.add(shadeEventCoordinator)
|
mCoordinators.add(shadeEventCoordinator)
|
||||||
mCoordinators.add(viewConfigCoordinator)
|
mCoordinators.add(viewConfigCoordinator)
|
||||||
mCoordinators.add(visualStabilityCoordinator)
|
mCoordinators.add(visualStabilityCoordinator)
|
||||||
mCoordinators.add(sensitiveContentCoordinator)
|
|
||||||
mCoordinators.add(activityLaunchAnimCoordinator)
|
mCoordinators.add(activityLaunchAnimCoordinator)
|
||||||
if (notifPipelineFlags.isSmartspaceDedupingEnabled()) {
|
if (notifPipelineFlags.isSmartspaceDedupingEnabled()) {
|
||||||
mCoordinators.add(smartspaceDedupingCoordinator)
|
mCoordinators.add(smartspaceDedupingCoordinator)
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.notification.collection.coordinator;
|
package com.android.systemui.statusbar.notification.collection.coordinator;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
@@ -29,13 +28,11 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga
|
|||||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
|
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
|
||||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
|
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
|
||||||
import com.android.systemui.statusbar.notification.collection.render.NodeController;
|
import com.android.systemui.statusbar.notification.collection.render.NodeController;
|
||||||
import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
|
|
||||||
import com.android.systemui.statusbar.notification.dagger.AlertingHeader;
|
import com.android.systemui.statusbar.notification.dagger.AlertingHeader;
|
||||||
import com.android.systemui.statusbar.notification.dagger.SilentHeader;
|
import com.android.systemui.statusbar.notification.dagger.SilentHeader;
|
||||||
import com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt;
|
import com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@@ -53,10 +50,10 @@ public class RankingCoordinator implements Coordinator {
|
|||||||
private final HighPriorityProvider mHighPriorityProvider;
|
private final HighPriorityProvider mHighPriorityProvider;
|
||||||
private final SectionClassifier mSectionClassifier;
|
private final SectionClassifier mSectionClassifier;
|
||||||
private final NodeController mSilentNodeController;
|
private final NodeController mSilentNodeController;
|
||||||
private final SectionHeaderController mSilentHeaderController;
|
|
||||||
private final NodeController mAlertingHeaderController;
|
private final NodeController mAlertingHeaderController;
|
||||||
private boolean mHasSilentEntries;
|
private final AlertingNotifSectioner mAlertingNotifSectioner = new AlertingNotifSectioner();
|
||||||
private boolean mHasMinimizedEntries;
|
private final SilentNotifSectioner mSilentNotifSectioner = new SilentNotifSectioner();
|
||||||
|
private final MinimizedNotifSectioner mMinimizedNotifSectioner = new MinimizedNotifSectioner();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public RankingCoordinator(
|
public RankingCoordinator(
|
||||||
@@ -64,14 +61,12 @@ public class RankingCoordinator implements Coordinator {
|
|||||||
HighPriorityProvider highPriorityProvider,
|
HighPriorityProvider highPriorityProvider,
|
||||||
SectionClassifier sectionClassifier,
|
SectionClassifier sectionClassifier,
|
||||||
@AlertingHeader NodeController alertingHeaderController,
|
@AlertingHeader NodeController alertingHeaderController,
|
||||||
@SilentHeader SectionHeaderController silentHeaderController,
|
|
||||||
@SilentHeader NodeController silentNodeController) {
|
@SilentHeader NodeController silentNodeController) {
|
||||||
mStatusBarStateController = statusBarStateController;
|
mStatusBarStateController = statusBarStateController;
|
||||||
mHighPriorityProvider = highPriorityProvider;
|
mHighPriorityProvider = highPriorityProvider;
|
||||||
mSectionClassifier = sectionClassifier;
|
mSectionClassifier = sectionClassifier;
|
||||||
mAlertingHeaderController = alertingHeaderController;
|
mAlertingHeaderController = alertingHeaderController;
|
||||||
mSilentNodeController = silentNodeController;
|
mSilentNodeController = silentNodeController;
|
||||||
mSilentHeaderController = silentHeaderController;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -95,82 +90,6 @@ public class RankingCoordinator implements Coordinator {
|
|||||||
return mMinimizedNotifSectioner;
|
return mMinimizedNotifSectioner;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final NotifSectioner mAlertingNotifSectioner = new NotifSectioner("Alerting",
|
|
||||||
NotificationPriorityBucketKt.BUCKET_ALERTING) {
|
|
||||||
@Override
|
|
||||||
public boolean isInSection(ListEntry entry) {
|
|
||||||
return mHighPriorityProvider.isHighPriority(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public NodeController getHeaderNodeController() {
|
|
||||||
// TODO: remove SHOW_ALL_SECTIONS, this redundant method, and mAlertingHeaderController
|
|
||||||
if (SHOW_ALL_SECTIONS) {
|
|
||||||
return mAlertingHeaderController;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final NotifSectioner mSilentNotifSectioner = new NotifSectioner("Silent",
|
|
||||||
NotificationPriorityBucketKt.BUCKET_SILENT) {
|
|
||||||
@Override
|
|
||||||
public boolean isInSection(ListEntry entry) {
|
|
||||||
return !mHighPriorityProvider.isHighPriority(entry)
|
|
||||||
&& !entry.getRepresentativeEntry().isAmbient();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public NodeController getHeaderNodeController() {
|
|
||||||
return mSilentNodeController;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public void onEntriesUpdated(@NonNull List<ListEntry> entries) {
|
|
||||||
mHasSilentEntries = false;
|
|
||||||
for (int i = 0; i < entries.size(); i++) {
|
|
||||||
if (entries.get(i).getRepresentativeEntry().getSbn().isClearable()) {
|
|
||||||
mHasSilentEntries = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mSilentHeaderController.setClearSectionEnabled(
|
|
||||||
mHasSilentEntries | mHasMinimizedEntries);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final NotifSectioner mMinimizedNotifSectioner = new NotifSectioner("Minimized",
|
|
||||||
NotificationPriorityBucketKt.BUCKET_SILENT) {
|
|
||||||
@Override
|
|
||||||
public boolean isInSection(ListEntry entry) {
|
|
||||||
return !mHighPriorityProvider.isHighPriority(entry)
|
|
||||||
&& entry.getRepresentativeEntry().isAmbient();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public NodeController getHeaderNodeController() {
|
|
||||||
return mSilentNodeController;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public void onEntriesUpdated(@NonNull List<ListEntry> entries) {
|
|
||||||
mHasMinimizedEntries = false;
|
|
||||||
for (int i = 0; i < entries.size(); i++) {
|
|
||||||
if (entries.get(i).getRepresentativeEntry().getSbn().isClearable()) {
|
|
||||||
mHasMinimizedEntries = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mSilentHeaderController.setClearSectionEnabled(
|
|
||||||
mHasSilentEntries | mHasMinimizedEntries);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether to filter out the given notification based the notification's Ranking object.
|
* Checks whether to filter out the given notification based the notification's Ranking object.
|
||||||
* NotifListBuilder invalidates the notification list each time the ranking is updated,
|
* NotifListBuilder invalidates the notification list each time the ranking is updated,
|
||||||
@@ -202,4 +121,64 @@ public class RankingCoordinator implements Coordinator {
|
|||||||
mDndVisualEffectsFilter.invalidateList();
|
mDndVisualEffectsFilter.invalidateList();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private class AlertingNotifSectioner extends NotifSectioner {
|
||||||
|
|
||||||
|
AlertingNotifSectioner() {
|
||||||
|
super("Alerting", NotificationPriorityBucketKt.BUCKET_ALERTING);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInSection(ListEntry entry) {
|
||||||
|
return mHighPriorityProvider.isHighPriority(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public NodeController getHeaderNodeController() {
|
||||||
|
// TODO: remove SHOW_ALL_SECTIONS, this redundant method, and mAlertingHeaderController
|
||||||
|
if (SHOW_ALL_SECTIONS) {
|
||||||
|
return mAlertingHeaderController;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SilentNotifSectioner extends NotifSectioner {
|
||||||
|
|
||||||
|
SilentNotifSectioner() {
|
||||||
|
super("Silent", NotificationPriorityBucketKt.BUCKET_SILENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInSection(ListEntry entry) {
|
||||||
|
return !mHighPriorityProvider.isHighPriority(entry)
|
||||||
|
&& !entry.getRepresentativeEntry().isAmbient();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public NodeController getHeaderNodeController() {
|
||||||
|
return mSilentNodeController;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MinimizedNotifSectioner extends NotifSectioner {
|
||||||
|
|
||||||
|
MinimizedNotifSectioner() {
|
||||||
|
super("Minimized", NotificationPriorityBucketKt.BUCKET_SILENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInSection(ListEntry entry) {
|
||||||
|
return !mHighPriorityProvider.isHighPriority(entry)
|
||||||
|
&& entry.getRepresentativeEntry().isAmbient();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public NodeController getHeaderNodeController() {
|
||||||
|
return mSilentNodeController;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,124 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2021 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.android.systemui.statusbar.notification.collection.coordinator
|
|
||||||
|
|
||||||
import android.os.UserHandle
|
|
||||||
import com.android.keyguard.KeyguardUpdateMonitor
|
|
||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager
|
|
||||||
import com.android.systemui.statusbar.StatusBarState
|
|
||||||
import com.android.systemui.statusbar.notification.DynamicPrivacyController
|
|
||||||
import com.android.systemui.statusbar.notification.collection.GroupEntry
|
|
||||||
import com.android.systemui.statusbar.notification.collection.ListEntry
|
|
||||||
import com.android.systemui.statusbar.notification.collection.NotifPipeline
|
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
|
||||||
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
|
|
||||||
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener
|
|
||||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator
|
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController
|
|
||||||
import dagger.Binds
|
|
||||||
import dagger.Module
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
@Module(includes = [PrivateSensitiveContentCoordinatorModule::class])
|
|
||||||
interface SensitiveContentCoordinatorModule
|
|
||||||
|
|
||||||
@Module
|
|
||||||
private interface PrivateSensitiveContentCoordinatorModule {
|
|
||||||
@Binds
|
|
||||||
fun bindCoordinator(impl: SensitiveContentCoordinatorImpl): SensitiveContentCoordinator
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Coordinates re-inflation and post-processing of sensitive notification content. */
|
|
||||||
interface SensitiveContentCoordinator : Coordinator
|
|
||||||
|
|
||||||
@CoordinatorScope
|
|
||||||
private class SensitiveContentCoordinatorImpl @Inject constructor(
|
|
||||||
private val dynamicPrivacyController: DynamicPrivacyController,
|
|
||||||
private val lockscreenUserManager: NotificationLockscreenUserManager,
|
|
||||||
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
|
|
||||||
private val statusBarStateController: StatusBarStateController,
|
|
||||||
private val keyguardStateController: KeyguardStateController
|
|
||||||
) : Invalidator("SensitiveContentInvalidator"),
|
|
||||||
SensitiveContentCoordinator,
|
|
||||||
DynamicPrivacyController.Listener,
|
|
||||||
OnBeforeRenderListListener {
|
|
||||||
|
|
||||||
override fun attach(pipeline: NotifPipeline) {
|
|
||||||
dynamicPrivacyController.addListener(this)
|
|
||||||
pipeline.addOnBeforeRenderListListener(this)
|
|
||||||
pipeline.addPreRenderInvalidator(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDynamicPrivacyChanged(): Unit = invalidateList()
|
|
||||||
|
|
||||||
override fun onBeforeRenderList(entries: List<ListEntry>) {
|
|
||||||
if (keyguardStateController.isKeyguardGoingAway() ||
|
|
||||||
statusBarStateController.getState() == StatusBarState.KEYGUARD &&
|
|
||||||
keyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing(
|
|
||||||
KeyguardUpdateMonitor.getCurrentUser())) {
|
|
||||||
// don't update yet if:
|
|
||||||
// - the keyguard is currently going away
|
|
||||||
// - LS is about to be dismissed by a biometric that bypasses LS (avoid notif flash)
|
|
||||||
|
|
||||||
// TODO(b/206118999): merge this class with KeyguardCoordinator which ensures the
|
|
||||||
// dependent state changes invalidate the pipeline
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val currentUserId = lockscreenUserManager.currentUserId
|
|
||||||
val devicePublic = lockscreenUserManager.isLockscreenPublicMode(currentUserId)
|
|
||||||
val deviceSensitive = devicePublic &&
|
|
||||||
!lockscreenUserManager.userAllowsPrivateNotificationsInPublic(currentUserId)
|
|
||||||
val dynamicallyUnlocked = dynamicPrivacyController.isDynamicallyUnlocked
|
|
||||||
for (entry in extractAllRepresentativeEntries(entries).filter { it.rowExists() }) {
|
|
||||||
val notifUserId = entry.sbn.user.identifier
|
|
||||||
val userLockscreen = devicePublic ||
|
|
||||||
lockscreenUserManager.isLockscreenPublicMode(notifUserId)
|
|
||||||
val userPublic = when {
|
|
||||||
// if we're not on the lockscreen, we're definitely private
|
|
||||||
!userLockscreen -> false
|
|
||||||
// we are on the lockscreen, so unless we're dynamically unlocked, we're
|
|
||||||
// definitely public
|
|
||||||
!dynamicallyUnlocked -> true
|
|
||||||
// we're dynamically unlocked, but check if the notification needs
|
|
||||||
// a separate challenge if it's from a work profile
|
|
||||||
else -> when (notifUserId) {
|
|
||||||
currentUserId -> false
|
|
||||||
UserHandle.USER_ALL -> false
|
|
||||||
else -> lockscreenUserManager.needsSeparateWorkChallenge(notifUserId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val needsRedaction = lockscreenUserManager.needsRedaction(entry)
|
|
||||||
val isSensitive = userPublic && needsRedaction
|
|
||||||
entry.setSensitive(isSensitive, deviceSensitive)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun extractAllRepresentativeEntries(
|
|
||||||
entries: List<ListEntry>
|
|
||||||
): Sequence<NotificationEntry> =
|
|
||||||
entries.asSequence().flatMap(::extractAllRepresentativeEntries)
|
|
||||||
|
|
||||||
private fun extractAllRepresentativeEntries(listEntry: ListEntry): Sequence<NotificationEntry> =
|
|
||||||
sequence {
|
|
||||||
listEntry.representativeEntry?.let { yield(it) }
|
|
||||||
if (listEntry is GroupEntry) {
|
|
||||||
yieldAll(extractAllRepresentativeEntries(listEntry.children))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -50,6 +50,8 @@ class StackCoordinator @Inject internal constructor(
|
|||||||
var hasClearableAlertingNotifs = false
|
var hasClearableAlertingNotifs = false
|
||||||
var hasNonClearableSilentNotifs = false
|
var hasNonClearableSilentNotifs = false
|
||||||
var hasClearableSilentNotifs = false
|
var hasClearableSilentNotifs = false
|
||||||
|
val clearableAlertingSensitiveNotifUsers = mutableSetOf<Int>()
|
||||||
|
val clearableSilentSensitiveNotifUsers = mutableSetOf<Int>()
|
||||||
entries.forEach {
|
entries.forEach {
|
||||||
val section = checkNotNull(it.section) { "Null section for ${it.key}" }
|
val section = checkNotNull(it.section) { "Null section for ${it.key}" }
|
||||||
val entry = checkNotNull(it.representativeEntry) { "Null notif entry for ${it.key}" }
|
val entry = checkNotNull(it.representativeEntry) { "Null notif entry for ${it.key}" }
|
||||||
@@ -63,13 +65,22 @@ class StackCoordinator @Inject internal constructor(
|
|||||||
!isSilent && isClearable -> hasClearableAlertingNotifs = true
|
!isSilent && isClearable -> hasClearableAlertingNotifs = true
|
||||||
!isSilent && !isClearable -> hasNonClearableAlertingNotifs = true
|
!isSilent && !isClearable -> hasNonClearableAlertingNotifs = true
|
||||||
}
|
}
|
||||||
|
if (isClearable && entry.hasSensitiveContents()) {
|
||||||
|
if (isSilent) {
|
||||||
|
clearableSilentSensitiveNotifUsers.add(entry.sbn.userId)
|
||||||
|
} else {
|
||||||
|
clearableAlertingSensitiveNotifUsers.add(entry.sbn.userId)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return NotifStats(
|
return NotifStats(
|
||||||
numActiveNotifs = entries.size,
|
numActiveNotifs = entries.size,
|
||||||
hasNonClearableAlertingNotifs = hasNonClearableAlertingNotifs,
|
hasNonClearableAlertingNotifs = hasNonClearableAlertingNotifs,
|
||||||
hasClearableAlertingNotifs = hasClearableAlertingNotifs,
|
hasClearableAlertingNotifs = hasClearableAlertingNotifs,
|
||||||
hasNonClearableSilentNotifs = hasNonClearableSilentNotifs,
|
hasNonClearableSilentNotifs = hasNonClearableSilentNotifs,
|
||||||
hasClearableSilentNotifs = hasClearableSilentNotifs
|
hasClearableSilentNotifs = hasClearableSilentNotifs,
|
||||||
|
clearableAlertingSensitiveNotifUsers = clearableAlertingSensitiveNotifUsers,
|
||||||
|
clearableSilentSensitiveNotifUsers = clearableSilentSensitiveNotifUsers
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,6 @@ import com.android.systemui.dagger.SysUISingleton
|
|||||||
import com.android.systemui.statusbar.notification.collection.coordinator.ActivityLaunchAnimCoordinatorModule
|
import com.android.systemui.statusbar.notification.collection.coordinator.ActivityLaunchAnimCoordinatorModule
|
||||||
import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators
|
import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators
|
||||||
import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinatorsImpl
|
import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinatorsImpl
|
||||||
import com.android.systemui.statusbar.notification.collection.coordinator.SensitiveContentCoordinatorModule
|
|
||||||
import dagger.Binds
|
import dagger.Binds
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
@@ -50,7 +49,6 @@ interface CoordinatorsSubcomponent {
|
|||||||
|
|
||||||
@Module(includes = [
|
@Module(includes = [
|
||||||
ActivityLaunchAnimCoordinatorModule::class,
|
ActivityLaunchAnimCoordinatorModule::class,
|
||||||
SensitiveContentCoordinatorModule::class,
|
|
||||||
])
|
])
|
||||||
private abstract class InternalCoordinatorsModule {
|
private abstract class InternalCoordinatorsModule {
|
||||||
@Binds
|
@Binds
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.notification.collection.inflation;
|
package com.android.systemui.statusbar.notification.collection.inflation;
|
||||||
|
|
||||||
|
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC;
|
||||||
|
|
||||||
import static java.util.Objects.requireNonNull;
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
@@ -249,10 +251,13 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
|
|||||||
RowContentBindParams params = mRowContentBindStage.getStageParams(entry);
|
RowContentBindParams params = mRowContentBindStage.getStageParams(entry);
|
||||||
params.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
|
params.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
|
||||||
params.setUseLowPriority(isLowPriority);
|
params.setUseLowPriority(isLowPriority);
|
||||||
|
boolean needsRedaction =
|
||||||
// TODO: Replace this API with RowContentBindParams directly. Also move to a separate
|
mNotificationLockscreenUserManager.notifNeedsRedactionInPublic(entry);
|
||||||
// redaction controller.
|
if (needsRedaction) {
|
||||||
row.setNeedsRedaction(mNotificationLockscreenUserManager.needsRedaction(entry));
|
params.requireContentViews(FLAG_CONTENT_VIEW_PUBLIC);
|
||||||
|
} else {
|
||||||
|
params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC);
|
||||||
|
}
|
||||||
|
|
||||||
params.rebindAllContentViews();
|
params.rebindAllContentViews();
|
||||||
mRowContentBindStage.requestRebind(entry, en -> {
|
mRowContentBindStage.requestRebind(entry, en -> {
|
||||||
|
|||||||
@@ -28,11 +28,21 @@ data class NotifStats(
|
|||||||
val hasNonClearableAlertingNotifs: Boolean,
|
val hasNonClearableAlertingNotifs: Boolean,
|
||||||
val hasClearableAlertingNotifs: Boolean,
|
val hasClearableAlertingNotifs: Boolean,
|
||||||
val hasNonClearableSilentNotifs: Boolean,
|
val hasNonClearableSilentNotifs: Boolean,
|
||||||
val hasClearableSilentNotifs: Boolean
|
val hasClearableSilentNotifs: Boolean,
|
||||||
|
val clearableAlertingSensitiveNotifUsers: Set<Int>,
|
||||||
|
val clearableSilentSensitiveNotifUsers: Set<Int>
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val empty = NotifStats(0, false, false, false, false)
|
val empty = NotifStats(
|
||||||
|
numActiveNotifs = 0,
|
||||||
|
hasNonClearableAlertingNotifs = false,
|
||||||
|
hasClearableAlertingNotifs = false,
|
||||||
|
hasNonClearableSilentNotifs = false,
|
||||||
|
hasClearableSilentNotifs = false,
|
||||||
|
clearableAlertingSensitiveNotifUsers = emptySet(),
|
||||||
|
clearableSilentSensitiveNotifUsers = emptySet(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -182,4 +182,4 @@ annotation class HeaderClickAction
|
|||||||
|
|
||||||
@Scope
|
@Scope
|
||||||
@Retention(AnnotationRetention.BINARY)
|
@Retention(AnnotationRetention.BINARY)
|
||||||
annotation class SectionHeaderScope
|
annotation class SectionHeaderScope
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import android.widget.ImageView
|
|||||||
import com.android.internal.statusbar.StatusBarIcon
|
import com.android.internal.statusbar.StatusBarIcon
|
||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager
|
||||||
import com.android.systemui.statusbar.StatusBarIconView
|
import com.android.systemui.statusbar.StatusBarIconView
|
||||||
import com.android.systemui.statusbar.notification.InflationException
|
import com.android.systemui.statusbar.notification.InflationException
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
||||||
@@ -49,31 +50,29 @@ import javax.inject.Inject
|
|||||||
class IconManager @Inject constructor(
|
class IconManager @Inject constructor(
|
||||||
private val notifCollection: CommonNotifCollection,
|
private val notifCollection: CommonNotifCollection,
|
||||||
private val launcherApps: LauncherApps,
|
private val launcherApps: LauncherApps,
|
||||||
private val iconBuilder: IconBuilder
|
private val iconBuilder: IconBuilder,
|
||||||
|
private val notifLockscreenUserManager: NotificationLockscreenUserManager
|
||||||
) : ConversationIconManager {
|
) : ConversationIconManager {
|
||||||
private var unimportantConversationKeys: Set<String> = emptySet()
|
private var unimportantConversationKeys: Set<String> = emptySet()
|
||||||
|
|
||||||
fun attach() {
|
fun attach() {
|
||||||
notifCollection.addCollectionListener(entryListener)
|
notifCollection.addCollectionListener(entryListener)
|
||||||
|
notifLockscreenUserManager.addOnNeedsRedactionInPublicChangedListener(sensitivityListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val entryListener = object : NotifCollectionListener {
|
private val entryListener = object : NotifCollectionListener {
|
||||||
override fun onEntryInit(entry: NotificationEntry) {
|
|
||||||
entry.addOnSensitivityChangedListener(sensitivityListener)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onEntryCleanUp(entry: NotificationEntry) {
|
|
||||||
entry.removeOnSensitivityChangedListener(sensitivityListener)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onRankingApplied() {
|
override fun onRankingApplied() {
|
||||||
// rankings affect whether a conversation is important, which can change the icons
|
// rankings affect whether a conversation is important, which can change the icons
|
||||||
recalculateForImportantConversationChange()
|
recalculateForImportantConversationChange()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val sensitivityListener = NotificationEntry.OnSensitivityChangedListener {
|
private val sensitivityListener = Runnable {
|
||||||
entry -> updateIconsSafe(entry)
|
for (entry in notifCollection.allNotifs) {
|
||||||
|
if (entry.hasSensitiveContents()) {
|
||||||
|
updateIconsSafe(entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun recalculateForImportantConversationChange() {
|
private fun recalculateForImportantConversationChange() {
|
||||||
@@ -182,12 +181,16 @@ class IconManager @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inline val NotificationEntry.needsRedactionInPublic: Boolean get() =
|
||||||
|
hasSensitiveContents() &&
|
||||||
|
notifLockscreenUserManager.sensitiveNotifsNeedRedactionInPublic(sbn.userId)
|
||||||
|
|
||||||
@Throws(InflationException::class)
|
@Throws(InflationException::class)
|
||||||
private fun getIconDescriptors(
|
private fun getIconDescriptors(
|
||||||
entry: NotificationEntry
|
entry: NotificationEntry
|
||||||
): Pair<StatusBarIcon, StatusBarIcon> {
|
): Pair<StatusBarIcon, StatusBarIcon> {
|
||||||
val iconDescriptor = getIconDescriptor(entry, false /* redact */)
|
val iconDescriptor = getIconDescriptor(entry, false /* redact */)
|
||||||
val sensitiveDescriptor = if (entry.isSensitive) {
|
val sensitiveDescriptor = if (entry.needsRedactionInPublic) {
|
||||||
getIconDescriptor(entry, true /* redact */)
|
getIconDescriptor(entry, true /* redact */)
|
||||||
} else {
|
} else {
|
||||||
iconDescriptor
|
iconDescriptor
|
||||||
@@ -310,7 +313,7 @@ class IconManager @Inject constructor(
|
|||||||
iconView === entry.icons.shelfIcon || iconView === entry.icons.aodIcon
|
iconView === entry.icons.shelfIcon || iconView === entry.icons.aodIcon
|
||||||
val isSmallIcon = iconDescriptor.icon.equals(entry.sbn.notification.smallIcon)
|
val isSmallIcon = iconDescriptor.icon.equals(entry.sbn.notification.smallIcon)
|
||||||
return isImportantConversation(entry) && !isSmallIcon &&
|
return isImportantConversation(entry) && !isSmallIcon &&
|
||||||
(!usedInSensitiveContext || !entry.isSensitive)
|
(!usedInSensitiveContext || !entry.needsRedactionInPublic)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isImportantConversation(entry: NotificationEntry): Boolean {
|
private fun isImportantConversation(entry: NotificationEntry): Boolean {
|
||||||
@@ -338,4 +341,4 @@ interface ConversationIconManager {
|
|||||||
* of a group from which the priority notification has been removed.
|
* of a group from which the priority notification has been removed.
|
||||||
*/
|
*/
|
||||||
fun setUnimportantConversations(keys: Collection<String>)
|
fun setUnimportantConversations(keys: Collection<String>)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,8 +93,8 @@ import com.android.systemui.statusbar.RemoteInputController;
|
|||||||
import com.android.systemui.statusbar.SmartReplyController;
|
import com.android.systemui.statusbar.SmartReplyController;
|
||||||
import com.android.systemui.statusbar.StatusBarIconView;
|
import com.android.systemui.statusbar.StatusBarIconView;
|
||||||
import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
|
import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
|
||||||
import com.android.systemui.statusbar.notification.LaunchAnimationParameters;
|
|
||||||
import com.android.systemui.statusbar.notification.FeedbackIcon;
|
import com.android.systemui.statusbar.notification.FeedbackIcon;
|
||||||
|
import com.android.systemui.statusbar.notification.LaunchAnimationParameters;
|
||||||
import com.android.systemui.statusbar.notification.NotificationFadeAware;
|
import com.android.systemui.statusbar.notification.NotificationFadeAware;
|
||||||
import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorController;
|
import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorController;
|
||||||
import com.android.systemui.statusbar.notification.NotificationUtils;
|
import com.android.systemui.statusbar.notification.NotificationUtils;
|
||||||
@@ -206,7 +206,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
|||||||
/** Are we showing the "public" version */
|
/** Are we showing the "public" version */
|
||||||
private boolean mShowingPublic;
|
private boolean mShowingPublic;
|
||||||
private boolean mSensitive;
|
private boolean mSensitive;
|
||||||
private boolean mSensitiveHiddenInGeneral;
|
|
||||||
private boolean mShowingPublicInitialized;
|
private boolean mShowingPublicInitialized;
|
||||||
private boolean mHideSensitiveForIntrinsicHeight;
|
private boolean mHideSensitiveForIntrinsicHeight;
|
||||||
private float mHeaderVisibleAmount = DEFAULT_HEADER_VISIBLE_AMOUNT;
|
private float mHeaderVisibleAmount = DEFAULT_HEADER_VISIBLE_AMOUNT;
|
||||||
@@ -1538,6 +1537,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
|||||||
mUseIncreasedHeadsUpHeight = use;
|
mUseIncreasedHeadsUpHeight = use;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove this method and mNeedsRedaction entirely once the old pipeline is gone
|
||||||
public void setNeedsRedaction(boolean needsRedaction) {
|
public void setNeedsRedaction(boolean needsRedaction) {
|
||||||
// TODO: Move inflation logic out of this call and remove this method
|
// TODO: Move inflation logic out of this call and remove this method
|
||||||
if (mNeedsRedaction != needsRedaction) {
|
if (mNeedsRedaction != needsRedaction) {
|
||||||
@@ -2622,9 +2622,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
|||||||
getShowingLayout().requestSelectLayout(needsAnimation || isUserLocked());
|
getShowingLayout().requestSelectLayout(needsAnimation || isUserLocked());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSensitive(boolean sensitive, boolean hideSensitive) {
|
public void setSensitive(boolean sensitive) {
|
||||||
mSensitive = sensitive;
|
mSensitive = sensitive;
|
||||||
mSensitiveHiddenInGeneral = hideSensitive;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -2714,7 +2713,15 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
|||||||
* see {@link NotificationEntry#isDismissable()}.
|
* see {@link NotificationEntry#isDismissable()}.
|
||||||
*/
|
*/
|
||||||
public boolean canViewBeDismissed() {
|
public boolean canViewBeDismissed() {
|
||||||
return mEntry.isDismissable() && (!shouldShowPublic() || !mSensitiveHiddenInGeneral);
|
// Entry not dismissable.
|
||||||
|
if (!mEntry.isDismissable()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Entry shouldn't be showing the public layout, it can be dismissed.
|
||||||
|
if (!shouldShowPublic()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2723,7 +2730,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
|||||||
* clearability see {@link NotificationEntry#isClearable()}.
|
* clearability see {@link NotificationEntry#isClearable()}.
|
||||||
*/
|
*/
|
||||||
public boolean canViewBeCleared() {
|
public boolean canViewBeCleared() {
|
||||||
return mEntry.isClearable() && (!shouldShowPublic() || !mSensitiveHiddenInGeneral);
|
return mEntry.isClearable() && !shouldShowPublic();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldShowPublic() {
|
private boolean shouldShowPublic() {
|
||||||
@@ -3487,10 +3494,28 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
|||||||
pw.print(", translation: " + getTranslation());
|
pw.print(", translation: " + getTranslation());
|
||||||
pw.print(", removed: " + isRemoved());
|
pw.print(", removed: " + isRemoved());
|
||||||
pw.print(", expandAnimationRunning: " + mExpandAnimationRunning);
|
pw.print(", expandAnimationRunning: " + mExpandAnimationRunning);
|
||||||
NotificationContentView showingLayout = getShowingLayout();
|
pw.print(", sensitive: " + mSensitive);
|
||||||
pw.print(", privateShowing: " + (showingLayout == mPrivateLayout));
|
pw.print(", hideSensitiveForIntrinsicHeight: " + mHideSensitiveForIntrinsicHeight);
|
||||||
pw.println();
|
pw.println(", privateShowing: " + !shouldShowPublic());
|
||||||
showingLayout.dump(pw, args);
|
pw.print("privateLayout: ");
|
||||||
|
if (mPrivateLayout != null) {
|
||||||
|
pw.println();
|
||||||
|
DumpUtilsKt.withIncreasedIndent(pw, () -> {
|
||||||
|
mPrivateLayout.dump(pw, args);
|
||||||
|
mPrivateLayout.dumpSmartReplies(pw);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
pw.println("null");
|
||||||
|
}
|
||||||
|
pw.print("publicLayout: ");
|
||||||
|
if (mPublicLayout != null) {
|
||||||
|
pw.println();
|
||||||
|
DumpUtilsKt.withIncreasedIndent(pw, () -> {
|
||||||
|
mPublicLayout.dump(pw, args);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
pw.println("null");
|
||||||
|
}
|
||||||
|
|
||||||
if (getViewState() != null) {
|
if (getViewState() != null) {
|
||||||
getViewState().dump(pw, args);
|
getViewState().dump(pw, args);
|
||||||
@@ -3516,8 +3541,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
|||||||
}
|
}
|
||||||
pw.decreaseIndent();
|
pw.decreaseIndent();
|
||||||
pw.println("}");
|
pw.println("}");
|
||||||
} else if (mPrivateLayout != null) {
|
|
||||||
mPrivateLayout.dumpSmartReplies(pw);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import com.android.systemui.plugins.FalsingManager;
|
|||||||
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
|
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
|
||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
import com.android.systemui.shared.plugins.PluginManager;
|
import com.android.systemui.shared.plugins.PluginManager;
|
||||||
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||||
import com.android.systemui.statusbar.NotificationMediaManager;
|
import com.android.systemui.statusbar.NotificationMediaManager;
|
||||||
import com.android.systemui.statusbar.SmartReplyController;
|
import com.android.systemui.statusbar.SmartReplyController;
|
||||||
import com.android.systemui.statusbar.notification.FeedbackIcon;
|
import com.android.systemui.statusbar.notification.FeedbackIcon;
|
||||||
@@ -69,6 +70,7 @@ import javax.inject.Named;
|
|||||||
public class ExpandableNotificationRowController implements NotifViewController {
|
public class ExpandableNotificationRowController implements NotifViewController {
|
||||||
private static final String TAG = "NotifRowController";
|
private static final String TAG = "NotifRowController";
|
||||||
private final ExpandableNotificationRow mView;
|
private final ExpandableNotificationRow mView;
|
||||||
|
private final NotificationLockscreenUserManager mLockscreenUserManager;
|
||||||
private final NotificationListContainer mListContainer;
|
private final NotificationListContainer mListContainer;
|
||||||
private final RemoteInputViewSubcomponent.Factory mRemoteInputViewSubcomponentFactory;
|
private final RemoteInputViewSubcomponent.Factory mRemoteInputViewSubcomponentFactory;
|
||||||
private final ActivatableNotificationViewController mActivatableNotificationViewController;
|
private final ActivatableNotificationViewController mActivatableNotificationViewController;
|
||||||
@@ -86,7 +88,6 @@ public class ExpandableNotificationRowController implements NotifViewController
|
|||||||
private final ExpandableNotificationRow.OnExpandClickListener mOnExpandClickListener;
|
private final ExpandableNotificationRow.OnExpandClickListener mOnExpandClickListener;
|
||||||
private final StatusBarStateController mStatusBarStateController;
|
private final StatusBarStateController mStatusBarStateController;
|
||||||
private final MetricsLogger mMetricsLogger;
|
private final MetricsLogger mMetricsLogger;
|
||||||
|
|
||||||
private final ExpandableNotificationRow.ExpansionLogger mExpansionLogger =
|
private final ExpandableNotificationRow.ExpansionLogger mExpansionLogger =
|
||||||
this::logNotificationExpansion;
|
this::logNotificationExpansion;
|
||||||
private final ExpandableNotificationRow.CoordinateOnClickListener mOnFeedbackClickListener;
|
private final ExpandableNotificationRow.CoordinateOnClickListener mOnFeedbackClickListener;
|
||||||
@@ -100,12 +101,12 @@ public class ExpandableNotificationRowController implements NotifViewController
|
|||||||
private final Optional<BubblesManager> mBubblesManagerOptional;
|
private final Optional<BubblesManager> mBubblesManagerOptional;
|
||||||
private final SmartReplyConstants mSmartReplyConstants;
|
private final SmartReplyConstants mSmartReplyConstants;
|
||||||
private final SmartReplyController mSmartReplyController;
|
private final SmartReplyController mSmartReplyController;
|
||||||
|
|
||||||
private final ExpandableNotificationRowDragController mDragController;
|
private final ExpandableNotificationRowDragController mDragController;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ExpandableNotificationRowController(
|
public ExpandableNotificationRowController(
|
||||||
ExpandableNotificationRow view,
|
ExpandableNotificationRow view,
|
||||||
|
NotificationLockscreenUserManager lockscreenUserManager,
|
||||||
ActivatableNotificationViewController activatableNotificationViewController,
|
ActivatableNotificationViewController activatableNotificationViewController,
|
||||||
RemoteInputViewSubcomponent.Factory rivSubcomponentFactory,
|
RemoteInputViewSubcomponent.Factory rivSubcomponentFactory,
|
||||||
MetricsLogger metricsLogger,
|
MetricsLogger metricsLogger,
|
||||||
@@ -135,6 +136,7 @@ public class ExpandableNotificationRowController implements NotifViewController
|
|||||||
Optional<BubblesManager> bubblesManagerOptional,
|
Optional<BubblesManager> bubblesManagerOptional,
|
||||||
ExpandableNotificationRowDragController dragController) {
|
ExpandableNotificationRowDragController dragController) {
|
||||||
mView = view;
|
mView = view;
|
||||||
|
mLockscreenUserManager = lockscreenUserManager;
|
||||||
mListContainer = listContainer;
|
mListContainer = listContainer;
|
||||||
mRemoteInputViewSubcomponentFactory = rivSubcomponentFactory;
|
mRemoteInputViewSubcomponentFactory = rivSubcomponentFactory;
|
||||||
mActivatableNotificationViewController = activatableNotificationViewController;
|
mActivatableNotificationViewController = activatableNotificationViewController;
|
||||||
@@ -214,6 +216,10 @@ public class ExpandableNotificationRowController implements NotifViewController
|
|||||||
mView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
|
mView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mLockscreenUserManager
|
||||||
|
.addOnNeedsRedactionInPublicChangedListener(mNeedsRedactionListener);
|
||||||
|
mNeedsRedactionListener.run();
|
||||||
|
|
||||||
mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
|
mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onViewAttachedToWindow(View v) {
|
public void onViewAttachedToWindow(View v) {
|
||||||
@@ -232,6 +238,14 @@ public class ExpandableNotificationRowController implements NotifViewController
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final Runnable mNeedsRedactionListener = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mView.setSensitive(
|
||||||
|
mLockscreenUserManager.notifNeedsRedactionInPublic(mView.getEntry()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private final StatusBarStateController.StateListener mStatusBarStateListener =
|
private final StatusBarStateController.StateListener mStatusBarStateListener =
|
||||||
new StatusBarStateController.StateListener() {
|
new StatusBarStateController.StateListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -333,4 +347,5 @@ public class ExpandableNotificationRowController implements NotifViewController
|
|||||||
public void setFeedbackIcon(@Nullable FeedbackIcon icon) {
|
public void setFeedbackIcon(@Nullable FeedbackIcon icon) {
|
||||||
mView.setFeedbackIcon(icon);
|
mView.setFeedbackIcon(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ import com.android.systemui.statusbar.policy.SmartReplyStateInflaterKt;
|
|||||||
import com.android.systemui.statusbar.policy.SmartReplyView;
|
import com.android.systemui.statusbar.policy.SmartReplyView;
|
||||||
import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent;
|
import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent;
|
||||||
import com.android.systemui.util.Compile;
|
import com.android.systemui.util.Compile;
|
||||||
|
import com.android.systemui.util.DumpUtilsKt;
|
||||||
import com.android.systemui.wmshell.BubblesManager;
|
import com.android.systemui.wmshell.BubblesManager;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
@@ -1994,22 +1995,33 @@ public class NotificationContentView extends FrameLayout implements Notification
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dump(PrintWriter pw, String[] args) {
|
public void dump(PrintWriter pwOriginal, String[] args) {
|
||||||
|
IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
|
||||||
pw.print("contentView visibility: " + getVisibility());
|
pw.print("contentView visibility: " + getVisibility());
|
||||||
pw.print(", alpha: " + getAlpha());
|
pw.print(", alpha: " + getAlpha());
|
||||||
pw.print(", clipBounds: " + getClipBounds());
|
pw.print(", clipBounds: " + getClipBounds());
|
||||||
pw.print(", contentHeight: " + mContentHeight);
|
pw.print(", contentHeight: " + mContentHeight);
|
||||||
pw.print(", visibleType: " + mVisibleType);
|
pw.println(", currentVisibleType: " + mVisibleType);
|
||||||
View view = getViewForVisibleType(mVisibleType);
|
DumpUtilsKt.withIncreasedIndent(pw, () -> {
|
||||||
pw.print(", visibleView ");
|
int[] visTypes = {
|
||||||
if (view != null) {
|
VISIBLE_TYPE_CONTRACTED,
|
||||||
pw.print(" visibility: " + view.getVisibility());
|
VISIBLE_TYPE_EXPANDED,
|
||||||
pw.print(", alpha: " + view.getAlpha());
|
VISIBLE_TYPE_HEADSUP,
|
||||||
pw.print(", clipBounds: " + view.getClipBounds());
|
VISIBLE_TYPE_SINGLELINE
|
||||||
} else {
|
};
|
||||||
pw.print("null");
|
for (int visType : visTypes) {
|
||||||
}
|
pw.print("visType: " + visType + " :: ");
|
||||||
pw.println();
|
View view = getViewForVisibleType(visType);
|
||||||
|
if (view != null) {
|
||||||
|
pw.print("visibility: " + view.getVisibility());
|
||||||
|
pw.print(", alpha: " + view.getAlpha());
|
||||||
|
pw.print(", clipBounds: " + view.getClipBounds());
|
||||||
|
} else {
|
||||||
|
pw.print("null");
|
||||||
|
}
|
||||||
|
pw.println();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Add any existing SmartReplyView to the dump */
|
/** Add any existing SmartReplyView to the dump */
|
||||||
|
|||||||
@@ -102,8 +102,9 @@ public final class RowContentBindParams {
|
|||||||
* @see InflationFlag
|
* @see InflationFlag
|
||||||
*/
|
*/
|
||||||
public void markContentViewsFreeable(@InflationFlag int contentViews) {
|
public void markContentViewsFreeable(@InflationFlag int contentViews) {
|
||||||
|
@InflationFlag int existingContentViews = contentViews &= mContentViews;
|
||||||
mContentViews &= ~contentViews;
|
mContentViews &= ~contentViews;
|
||||||
mDirtyContentViews &= ~contentViews;
|
mDirtyContentViews |= existingContentViews;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @InflationFlag int getContentViews() {
|
public @InflationFlag int getContentViews() {
|
||||||
|
|||||||
@@ -216,6 +216,9 @@ public class NotificationStackScrollLayoutController {
|
|||||||
mBarState = mStatusBarStateController.getState();
|
mBarState = mStatusBarStateController.getState();
|
||||||
mStatusBarStateController.addCallback(
|
mStatusBarStateController.addCallback(
|
||||||
mStateListener, SysuiStatusBarStateController.RANK_STACK_SCROLLER);
|
mStateListener, SysuiStatusBarStateController.RANK_STACK_SCROLLER);
|
||||||
|
mLockscreenUserManager.addOnNeedsRedactionInPublicChangedListener(
|
||||||
|
mOnNeedsRedactionInPublicChangedListener);
|
||||||
|
updateClearButtonVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -223,6 +226,8 @@ public class NotificationStackScrollLayoutController {
|
|||||||
mConfigurationController.removeCallback(mConfigurationListener);
|
mConfigurationController.removeCallback(mConfigurationListener);
|
||||||
mZenModeController.removeCallback(mZenModeControllerCallback);
|
mZenModeController.removeCallback(mZenModeControllerCallback);
|
||||||
mStatusBarStateController.removeCallback(mStateListener);
|
mStatusBarStateController.removeCallback(mStateListener);
|
||||||
|
mLockscreenUserManager.removeOnNeedsRedactionInPublicChangedListener(
|
||||||
|
mOnNeedsRedactionInPublicChangedListener);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -326,6 +331,7 @@ public class NotificationStackScrollLayoutController {
|
|||||||
mLockscreenUserManager.isAnyProfilePublicMode());
|
mLockscreenUserManager.isAnyProfilePublicMode());
|
||||||
mView.onStatePostChange(mStatusBarStateController.fromShadeLocked());
|
mView.onStatePostChange(mStatusBarStateController.fromShadeLocked());
|
||||||
mNotificationEntryManager.updateNotifications("CentralSurfaces state changed");
|
mNotificationEntryManager.updateNotifications("CentralSurfaces state changed");
|
||||||
|
updateClearButtonVisibility();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -338,6 +344,17 @@ public class NotificationStackScrollLayoutController {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private final Runnable mOnNeedsRedactionInPublicChangedListener = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Whether or not the notification needs redaction when in public has changed, but if
|
||||||
|
// we're not actually in public, then we don't need to update anything.
|
||||||
|
if (mLockscreenUserManager.isAnyProfilePublicMode()) {
|
||||||
|
updateClearButtonVisibility();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the overexpansion of the panel to be applied to the view.
|
* Set the overexpansion of the panel to be applied to the view.
|
||||||
*/
|
*/
|
||||||
@@ -1274,12 +1291,44 @@ public class NotificationStackScrollLayoutController {
|
|||||||
return hasNotifications(selection, true /* clearable */);
|
return hasNotifications(selection, true /* clearable */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasRedactedClearableSilentNotifs() {
|
||||||
|
if (!mLockscreenUserManager.isAnyProfilePublicMode()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int userId : mNotifStats.getClearableSilentSensitiveNotifUsers()) {
|
||||||
|
if (mLockscreenUserManager.sensitiveNotifsNeedRedactionInPublic(userId)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasClearableSilentNotifs() {
|
||||||
|
return mNotifStats.getHasClearableSilentNotifs() && !hasRedactedClearableSilentNotifs();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasRedactedClearableAlertingNotifs() {
|
||||||
|
if (!mLockscreenUserManager.isAnyProfilePublicMode()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int userId : mNotifStats.getClearableAlertingSensitiveNotifUsers()) {
|
||||||
|
if (mLockscreenUserManager.sensitiveNotifsNeedRedactionInPublic(userId)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasClearableAlertingNotifs() {
|
||||||
|
return mNotifStats.getHasClearableAlertingNotifs() && !hasRedactedClearableAlertingNotifs();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasNotifications(@SelectedRows int selection, boolean isClearable) {
|
public boolean hasNotifications(@SelectedRows int selection, boolean isClearable) {
|
||||||
boolean hasAlertingMatchingClearable = isClearable
|
boolean hasAlertingMatchingClearable = isClearable
|
||||||
? mNotifStats.getHasClearableAlertingNotifs()
|
? hasClearableAlertingNotifs()
|
||||||
: mNotifStats.getHasNonClearableAlertingNotifs();
|
: mNotifStats.getHasNonClearableAlertingNotifs();
|
||||||
boolean hasSilentMatchingClearable = isClearable
|
boolean hasSilentMatchingClearable = isClearable
|
||||||
? mNotifStats.getHasClearableSilentNotifs()
|
? hasClearableSilentNotifs()
|
||||||
: mNotifStats.getHasNonClearableSilentNotifs();
|
: mNotifStats.getHasNonClearableSilentNotifs();
|
||||||
switch (selection) {
|
switch (selection) {
|
||||||
case ROWS_GENTLE:
|
case ROWS_GENTLE:
|
||||||
@@ -1579,6 +1628,15 @@ public class NotificationStackScrollLayoutController {
|
|||||||
mNotificationActivityStarter = activityStarter;
|
mNotificationActivityStarter = activityStarter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateClearButtonVisibility() {
|
||||||
|
updateClearSilentButton();
|
||||||
|
updateFooter();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateClearSilentButton() {
|
||||||
|
mSilentHeaderController.setClearSectionEnabled(hasClearableSilentNotifs());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enum for UiEvent logged from this class
|
* Enum for UiEvent logged from this class
|
||||||
*/
|
*/
|
||||||
@@ -1904,6 +1962,7 @@ public class NotificationStackScrollLayoutController {
|
|||||||
@Override
|
@Override
|
||||||
public void setNotifStats(@NonNull NotifStats notifStats) {
|
public void setNotifStats(@NonNull NotifStats notifStats) {
|
||||||
mNotifStats = notifStats;
|
mNotifStats = notifStats;
|
||||||
|
updateClearSilentButton();
|
||||||
updateFooter();
|
updateFooter();
|
||||||
updateShowEmptyShadeView();
|
updateShowEmptyShadeView();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
|||||||
import com.android.systemui.statusbar.CommandQueue;
|
import com.android.systemui.statusbar.CommandQueue;
|
||||||
import com.android.systemui.statusbar.CrossFadeHelper;
|
import com.android.systemui.statusbar.CrossFadeHelper;
|
||||||
import com.android.systemui.statusbar.HeadsUpStatusBarView;
|
import com.android.systemui.statusbar.HeadsUpStatusBarView;
|
||||||
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||||
import com.android.systemui.statusbar.StatusBarState;
|
import com.android.systemui.statusbar.StatusBarState;
|
||||||
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
|
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||||
@@ -40,8 +41,8 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
|
|||||||
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
|
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
|
||||||
import com.android.systemui.util.ViewController;
|
import com.android.systemui.util.ViewController;
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@@ -61,17 +62,17 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar
|
|||||||
private final NotificationIconAreaController mNotificationIconAreaController;
|
private final NotificationIconAreaController mNotificationIconAreaController;
|
||||||
private final HeadsUpManagerPhone mHeadsUpManager;
|
private final HeadsUpManagerPhone mHeadsUpManager;
|
||||||
private final NotificationStackScrollLayoutController mStackScrollerController;
|
private final NotificationStackScrollLayoutController mStackScrollerController;
|
||||||
|
|
||||||
private final DarkIconDispatcher mDarkIconDispatcher;
|
private final DarkIconDispatcher mDarkIconDispatcher;
|
||||||
private final NotificationPanelViewController mNotificationPanelViewController;
|
private final NotificationPanelViewController mNotificationPanelViewController;
|
||||||
private final Consumer<ExpandableNotificationRow>
|
private final Consumer<ExpandableNotificationRow> mSetTrackingHeadsUp =
|
||||||
mSetTrackingHeadsUp = this::setTrackingHeadsUp;
|
this::setTrackingHeadsUp;
|
||||||
private final BiConsumer<Float, Float> mSetExpandedHeight = this::setAppearFraction;
|
private final BiConsumer<Float, Float> mSetExpandedHeight = this::setAppearFraction;
|
||||||
private final KeyguardBypassController mBypassController;
|
private final KeyguardBypassController mBypassController;
|
||||||
private final StatusBarStateController mStatusBarStateController;
|
private final StatusBarStateController mStatusBarStateController;
|
||||||
private final CommandQueue mCommandQueue;
|
private final CommandQueue mCommandQueue;
|
||||||
private final NotificationWakeUpCoordinator mWakeUpCoordinator;
|
private final NotificationWakeUpCoordinator mWakeUpCoordinator;
|
||||||
|
private final NotificationLockscreenUserManager mNotifLockscreenUserManager;
|
||||||
|
private final Runnable mRedactionChanged = this::updateRedaction;
|
||||||
private final View mClockView;
|
private final View mClockView;
|
||||||
private final Optional<View> mOperatorNameViewOptional;
|
private final Optional<View> mOperatorNameViewOptional;
|
||||||
|
|
||||||
@@ -90,6 +91,13 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar
|
|||||||
};
|
};
|
||||||
private boolean mAnimationsEnabled = true;
|
private boolean mAnimationsEnabled = true;
|
||||||
private final KeyguardStateController mKeyguardStateController;
|
private final KeyguardStateController mKeyguardStateController;
|
||||||
|
private final StatusBarStateController.StateListener mStatusBarStateListener =
|
||||||
|
new StatusBarStateController.StateListener() {
|
||||||
|
@Override
|
||||||
|
public void onStatePostChange() {
|
||||||
|
updateRedaction();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@Inject
|
@Inject
|
||||||
@@ -98,6 +106,7 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar
|
|||||||
HeadsUpManagerPhone headsUpManager,
|
HeadsUpManagerPhone headsUpManager,
|
||||||
StatusBarStateController stateController,
|
StatusBarStateController stateController,
|
||||||
KeyguardBypassController bypassController,
|
KeyguardBypassController bypassController,
|
||||||
|
NotificationLockscreenUserManager notifLockscreenUserManager,
|
||||||
NotificationWakeUpCoordinator wakeUpCoordinator,
|
NotificationWakeUpCoordinator wakeUpCoordinator,
|
||||||
DarkIconDispatcher darkIconDispatcher,
|
DarkIconDispatcher darkIconDispatcher,
|
||||||
KeyguardStateController keyguardStateController,
|
KeyguardStateController keyguardStateController,
|
||||||
@@ -125,6 +134,7 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar
|
|||||||
mClockView = clockView;
|
mClockView = clockView;
|
||||||
mOperatorNameViewOptional = operatorNameViewOptional;
|
mOperatorNameViewOptional = operatorNameViewOptional;
|
||||||
mDarkIconDispatcher = darkIconDispatcher;
|
mDarkIconDispatcher = darkIconDispatcher;
|
||||||
|
mNotifLockscreenUserManager = notifLockscreenUserManager;
|
||||||
|
|
||||||
mView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
|
mView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -156,6 +166,8 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar
|
|||||||
mNotificationPanelViewController.setHeadsUpAppearanceController(this);
|
mNotificationPanelViewController.setHeadsUpAppearanceController(this);
|
||||||
mStackScrollerController.addOnExpandedHeightChangedListener(mSetExpandedHeight);
|
mStackScrollerController.addOnExpandedHeightChangedListener(mSetExpandedHeight);
|
||||||
mDarkIconDispatcher.addDarkReceiver(this);
|
mDarkIconDispatcher.addDarkReceiver(this);
|
||||||
|
mNotifLockscreenUserManager.addOnNeedsRedactionInPublicChangedListener(mRedactionChanged);
|
||||||
|
mStatusBarStateController.addCallback(mStatusBarStateListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -167,6 +179,9 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar
|
|||||||
mNotificationPanelViewController.setHeadsUpAppearanceController(null);
|
mNotificationPanelViewController.setHeadsUpAppearanceController(null);
|
||||||
mStackScrollerController.removeOnExpandedHeightChangedListener(mSetExpandedHeight);
|
mStackScrollerController.removeOnExpandedHeightChangedListener(mSetExpandedHeight);
|
||||||
mDarkIconDispatcher.removeDarkReceiver(this);
|
mDarkIconDispatcher.removeDarkReceiver(this);
|
||||||
|
mNotifLockscreenUserManager
|
||||||
|
.removeOnNeedsRedactionInPublicChangedListener(mRedactionChanged);
|
||||||
|
mStatusBarStateController.removeCallback(mStatusBarStateListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateIsolatedIconLocation(boolean requireStateUpdate) {
|
private void updateIsolatedIconLocation(boolean requireStateUpdate) {
|
||||||
@@ -180,6 +195,19 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar
|
|||||||
updateHeader(entry);
|
updateHeader(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateRedaction() {
|
||||||
|
NotificationEntry showingEntry = mView.getShowingEntry();
|
||||||
|
if (showingEntry == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int notifUserId = showingEntry.getSbn().getUserId();
|
||||||
|
boolean redactSensitiveContent =
|
||||||
|
mNotifLockscreenUserManager.isLockscreenPublicMode(notifUserId)
|
||||||
|
&& mNotifLockscreenUserManager
|
||||||
|
.sensitiveNotifsNeedRedactionInPublic(notifUserId);
|
||||||
|
mView.setRedactSensitiveContent(redactSensitiveContent);
|
||||||
|
}
|
||||||
|
|
||||||
private void updateTopEntry() {
|
private void updateTopEntry() {
|
||||||
NotificationEntry newEntry = null;
|
NotificationEntry newEntry = null;
|
||||||
if (shouldBeVisible()) {
|
if (shouldBeVisible()) {
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_N
|
|||||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
|
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
|
||||||
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
|
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
|
||||||
import static com.android.systemui.statusbar.StatusBarState.SHADE;
|
import static com.android.systemui.statusbar.StatusBarState.SHADE;
|
||||||
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
|
|
||||||
import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_FOLD_TO_AOD;
|
import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_FOLD_TO_AOD;
|
||||||
import static com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManagerKt.STATE_CLOSED;
|
import static com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManagerKt.STATE_CLOSED;
|
||||||
import static com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManagerKt.STATE_OPEN;
|
import static com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManagerKt.STATE_OPEN;
|
||||||
@@ -3944,10 +3943,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasActiveClearableNotifications() {
|
|
||||||
return mNotificationStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RemoteInputController.Delegate createRemoteInputDelegate() {
|
public RemoteInputController.Delegate createRemoteInputDelegate() {
|
||||||
return mNotificationStackScrollLayoutController.createDelegate();
|
return mNotificationStackScrollLayoutController.createDelegate();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -411,8 +411,8 @@ class StatusBarNotificationPresenter implements NotificationPresenter,
|
|||||||
if (nowExpanded) {
|
if (nowExpanded) {
|
||||||
if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
|
if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
|
||||||
mShadeTransitionController.goToLockedShade(clickedEntry.getRow());
|
mShadeTransitionController.goToLockedShade(clickedEntry.getRow());
|
||||||
} else if (clickedEntry.isSensitive()
|
} else if (mDynamicPrivacyController.isInLockedDownShade()
|
||||||
&& mDynamicPrivacyController.isInLockedDownShade()) {
|
&& mLockscreenUserManager.notifNeedsRedactionInPublic(clickedEntry)) {
|
||||||
mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
|
mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
|
||||||
mActivityStarter.dismissKeyguardThenExecute(() -> false /* dismissAction */
|
mActivityStarter.dismissKeyguardThenExecute(() -> false /* dismissAction */
|
||||||
, null /* cancelRunnable */, false /* afterKeyguardGone */);
|
, null /* cancelRunnable */, false /* afterKeyguardGone */);
|
||||||
@@ -480,7 +480,7 @@ class StatusBarNotificationPresenter implements NotificationPresenter,
|
|||||||
.isLockscreenPublicMode(mLockscreenUserManager.getCurrentUserId());
|
.isLockscreenPublicMode(mLockscreenUserManager.getCurrentUserId());
|
||||||
boolean userPublic = devicePublic
|
boolean userPublic = devicePublic
|
||||||
|| mLockscreenUserManager.isLockscreenPublicMode(sbn.getUserId());
|
|| mLockscreenUserManager.isLockscreenPublicMode(sbn.getUserId());
|
||||||
boolean needsRedaction = mLockscreenUserManager.needsRedaction(entry);
|
boolean needsRedaction = mLockscreenUserManager.notifNeedsRedactionInPublic(entry);
|
||||||
if (userPublic && needsRedaction) {
|
if (userPublic && needsRedaction) {
|
||||||
// TODO(b/135046837): we can probably relax this with dynamic privacy
|
// TODO(b/135046837): we can probably relax this with dynamic privacy
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -130,8 +130,8 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
|
|||||||
whenever(statusbarStateController.state).thenReturn(StatusBarState.KEYGUARD)
|
whenever(statusbarStateController.state).thenReturn(StatusBarState.KEYGUARD)
|
||||||
whenever(nsslController.isInLockedDownShade).thenReturn(false)
|
whenever(nsslController.isInLockedDownShade).thenReturn(false)
|
||||||
whenever(qS.isFullyCollapsed).thenReturn(true)
|
whenever(qS.isFullyCollapsed).thenReturn(true)
|
||||||
whenever(lockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn(
|
whenever(lockScreenUserManager.sensitiveNotifsNeedRedactionInPublic(anyInt()))
|
||||||
true)
|
.thenReturn(false)
|
||||||
whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(true)
|
whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(true)
|
||||||
whenever(lockScreenUserManager.isLockscreenPublicMode(anyInt())).thenReturn(true)
|
whenever(lockScreenUserManager.isLockscreenPublicMode(anyInt())).thenReturn(true)
|
||||||
whenever(falsingCollector.shouldEnforceBouncer()).thenReturn(false)
|
whenever(falsingCollector.shouldEnforceBouncer()).thenReturn(false)
|
||||||
@@ -207,8 +207,8 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testTriggeringBouncerWhenPrivateNotificationsArentAllowed() {
|
fun testTriggeringBouncerWhenPrivateNotificationsArentAllowed() {
|
||||||
whenever(lockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn(
|
whenever(lockScreenUserManager.sensitiveNotifsNeedRedactionInPublic(anyInt()))
|
||||||
false)
|
.thenReturn(true)
|
||||||
transitionController.goToLockedShade(null)
|
transitionController.goToLockedShade(null)
|
||||||
verify(statusbarStateController, never()).setState(anyInt())
|
verify(statusbarStateController, never()).setState(anyInt())
|
||||||
verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true)
|
verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true)
|
||||||
|
|||||||
@@ -53,11 +53,13 @@ import android.testing.TestableLooper;
|
|||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||||
import com.android.systemui.Dependency;
|
import com.android.systemui.Dependency;
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||||
import com.android.systemui.dump.DumpManager;
|
import com.android.systemui.dump.DumpManager;
|
||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
|
import com.android.systemui.recents.OverviewProxyService;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager.KeyguardNotificationSuppressor;
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager.KeyguardNotificationSuppressor;
|
||||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||||
@@ -106,6 +108,10 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
|
|||||||
private BroadcastDispatcher mBroadcastDispatcher;
|
private BroadcastDispatcher mBroadcastDispatcher;
|
||||||
@Mock
|
@Mock
|
||||||
private KeyguardStateController mKeyguardStateController;
|
private KeyguardStateController mKeyguardStateController;
|
||||||
|
@Mock
|
||||||
|
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||||
|
@Mock
|
||||||
|
private OverviewProxyService mOverviewProxyService;
|
||||||
|
|
||||||
private UserInfo mCurrentUser;
|
private UserInfo mCurrentUser;
|
||||||
private UserInfo mSecondaryUser;
|
private UserInfo mSecondaryUser;
|
||||||
@@ -119,7 +125,6 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
|
|||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
|
|
||||||
|
|
||||||
int currentUserId = ActivityManager.getCurrentUser();
|
int currentUserId = ActivityManager.getCurrentUser();
|
||||||
mSettings = new FakeSettings();
|
mSettings = new FakeSettings();
|
||||||
@@ -212,7 +217,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
|
|||||||
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
|
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
|
||||||
|
|
||||||
// THEN current user's notification is redacted
|
// THEN current user's notification is redacted
|
||||||
assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
|
assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mCurrentUserNotif));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -223,7 +228,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
|
|||||||
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
|
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
|
||||||
|
|
||||||
// THEN current user's notification isn't redacted
|
// THEN current user's notification isn't redacted
|
||||||
assertFalse(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
|
assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mCurrentUserNotif));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -234,7 +239,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
|
|||||||
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
|
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
|
||||||
|
|
||||||
// THEN work profile notification is redacted
|
// THEN work profile notification is redacted
|
||||||
assertTrue(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
|
assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mWorkProfileNotif));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -245,7 +250,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
|
|||||||
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
|
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
|
||||||
|
|
||||||
// THEN work profile notification isn't redacted
|
// THEN work profile notification isn't redacted
|
||||||
assertFalse(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
|
assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mWorkProfileNotif));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -260,11 +265,11 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
|
|||||||
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
|
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
|
||||||
|
|
||||||
// THEN the work profile notification doesn't need to be redacted
|
// THEN the work profile notification doesn't need to be redacted
|
||||||
assertFalse(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
|
assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mWorkProfileNotif));
|
||||||
|
|
||||||
// THEN the current user and secondary user notifications do need to be redacted
|
// THEN the current user and secondary user notifications do need to be redacted
|
||||||
assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
|
assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mCurrentUserNotif));
|
||||||
assertTrue(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif));
|
assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mSecondaryUserNotif));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -279,11 +284,11 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
|
|||||||
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
|
mLockscreenUserManager.getLockscreenSettingsObserverForTest().onChange(false);
|
||||||
|
|
||||||
// THEN the work profile notification needs to be redacted
|
// THEN the work profile notification needs to be redacted
|
||||||
assertTrue(mLockscreenUserManager.needsRedaction(mWorkProfileNotif));
|
assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mWorkProfileNotif));
|
||||||
|
|
||||||
// THEN the current user and secondary user notifications don't need to be redacted
|
// THEN the current user and secondary user notifications don't need to be redacted
|
||||||
assertFalse(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
|
assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mCurrentUserNotif));
|
||||||
assertFalse(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif));
|
assertFalse(mLockscreenUserManager.notifNeedsRedactionInPublic(mSecondaryUserNotif));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -298,7 +303,7 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
|
|||||||
|
|
||||||
// THEN the secondary profile notification still needs to be redacted because the current
|
// THEN the secondary profile notification still needs to be redacted because the current
|
||||||
// user's setting takes precedence
|
// user's setting takes precedence
|
||||||
assertTrue(mLockscreenUserManager.needsRedaction(mSecondaryUserNotif));
|
assertTrue(mLockscreenUserManager.notifNeedsRedactionInPublic(mSecondaryUserNotif));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -418,9 +423,12 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
|
|||||||
context,
|
context,
|
||||||
mBroadcastDispatcher,
|
mBroadcastDispatcher,
|
||||||
mDevicePolicyManager,
|
mDevicePolicyManager,
|
||||||
|
mKeyguardUpdateMonitor,
|
||||||
|
() -> mEntryManager,
|
||||||
|
() -> mOverviewProxyService,
|
||||||
mUserManager,
|
mUserManager,
|
||||||
(() -> mVisibilityProvider),
|
() -> mVisibilityProvider,
|
||||||
(() -> mNotifCollection),
|
() -> mNotifCollection,
|
||||||
mClickNotifier,
|
mClickNotifier,
|
||||||
NotificationLockscreenUserManagerTest.this.mKeyguardManager,
|
NotificationLockscreenUserManagerTest.this.mKeyguardManager,
|
||||||
mStatusBarStateController,
|
mStatusBarStateController,
|
||||||
|
|||||||
@@ -124,8 +124,8 @@ public class DynamicPrivacyControllerTest extends SysuiTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void allowPrivateNotificationsInPublic(boolean allow) {
|
private void allowPrivateNotificationsInPublic(boolean allow) {
|
||||||
when(mLockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn(
|
when(mLockScreenUserManager.sensitiveNotifsNeedRedactionInPublic(anyInt())).thenReturn(
|
||||||
allow);
|
!allow);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import static org.junit.Assert.assertEquals;
|
|||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
@@ -33,7 +32,6 @@ import android.app.Notification;
|
|||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
@@ -41,7 +39,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
|||||||
import com.android.systemui.statusbar.RankingBuilder;
|
import com.android.systemui.statusbar.RankingBuilder;
|
||||||
import com.android.systemui.statusbar.SbnBuilder;
|
import com.android.systemui.statusbar.SbnBuilder;
|
||||||
import com.android.systemui.statusbar.notification.SectionClassifier;
|
import com.android.systemui.statusbar.notification.SectionClassifier;
|
||||||
import com.android.systemui.statusbar.notification.collection.ListEntry;
|
|
||||||
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
|
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
|
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
|
||||||
@@ -49,7 +46,6 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga
|
|||||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
|
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
|
||||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
|
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
|
||||||
import com.android.systemui.statusbar.notification.collection.render.NodeController;
|
import com.android.systemui.statusbar.notification.collection.render.NodeController;
|
||||||
import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -72,7 +68,6 @@ public class RankingCoordinatorTest extends SysuiTestCase {
|
|||||||
@Mock private NotifPipeline mNotifPipeline;
|
@Mock private NotifPipeline mNotifPipeline;
|
||||||
@Mock private NodeController mAlertingHeaderController;
|
@Mock private NodeController mAlertingHeaderController;
|
||||||
@Mock private NodeController mSilentNodeController;
|
@Mock private NodeController mSilentNodeController;
|
||||||
@Mock private SectionHeaderController mSilentHeaderController;
|
|
||||||
|
|
||||||
@Captor private ArgumentCaptor<NotifFilter> mNotifFilterCaptor;
|
@Captor private ArgumentCaptor<NotifFilter> mNotifFilterCaptor;
|
||||||
|
|
||||||
@@ -94,7 +89,6 @@ public class RankingCoordinatorTest extends SysuiTestCase {
|
|||||||
mHighPriorityProvider,
|
mHighPriorityProvider,
|
||||||
mSectionClassifier,
|
mSectionClassifier,
|
||||||
mAlertingHeaderController,
|
mAlertingHeaderController,
|
||||||
mSilentHeaderController,
|
|
||||||
mSilentNodeController);
|
mSilentNodeController);
|
||||||
mEntry = spy(new NotificationEntryBuilder().build());
|
mEntry = spy(new NotificationEntryBuilder().build());
|
||||||
mEntry.setRanking(getRankingForUnfilteredNotif().build());
|
mEntry.setRanking(getRankingForUnfilteredNotif().build());
|
||||||
@@ -111,25 +105,6 @@ public class RankingCoordinatorTest extends SysuiTestCase {
|
|||||||
mSections.addAll(Arrays.asList(mAlertingSectioner, mSilentSectioner, mMinimizedSectioner));
|
mSections.addAll(Arrays.asList(mAlertingSectioner, mSilentSectioner, mMinimizedSectioner));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSilentHeaderClearableChildrenUpdate() {
|
|
||||||
ListEntry listEntry = new ListEntry(mEntry.getKey(), 0L) {
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public NotificationEntry getRepresentativeEntry() {
|
|
||||||
return mEntry;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
setRankingAmbient(false);
|
|
||||||
setSbnClearable(true);
|
|
||||||
mSilentSectioner.onEntriesUpdated(Arrays.asList(listEntry));
|
|
||||||
verify(mSilentHeaderController).setClearSectionEnabled(eq(true));
|
|
||||||
|
|
||||||
setSbnClearable(false);
|
|
||||||
mSilentSectioner.onEntriesUpdated(Arrays.asList(listEntry));
|
|
||||||
verify(mSilentHeaderController).setClearSectionEnabled(eq(false));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUnfilteredState() {
|
public void testUnfilteredState() {
|
||||||
// GIVEN no suppressed visual effects + app not suspended
|
// GIVEN no suppressed visual effects + app not suspended
|
||||||
@@ -225,46 +200,6 @@ public class RankingCoordinatorTest extends SysuiTestCase {
|
|||||||
assertInSection(mEntry, mSilentSectioner);
|
assertInSection(mEntry, mSilentSectioner);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testClearableSilentSection() {
|
|
||||||
when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(false);
|
|
||||||
setSbnClearable(true);
|
|
||||||
setRankingAmbient(false);
|
|
||||||
mSilentSectioner.onEntriesUpdated(Arrays.asList(mEntry));
|
|
||||||
verify(mSilentHeaderController).setClearSectionEnabled(eq(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testClearableMinimizedSection() {
|
|
||||||
when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(false);
|
|
||||||
setSbnClearable(true);
|
|
||||||
setRankingAmbient(true);
|
|
||||||
mMinimizedSectioner.onEntriesUpdated(Arrays.asList(mEntry));
|
|
||||||
verify(mSilentHeaderController).setClearSectionEnabled(eq(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNotClearableSilentSection() {
|
|
||||||
setSbnClearable(false);
|
|
||||||
when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(false);
|
|
||||||
setRankingAmbient(false);
|
|
||||||
mSilentSectioner.onEntriesUpdated(Arrays.asList(mEntry));
|
|
||||||
mMinimizedSectioner.onEntriesUpdated(Arrays.asList(mEntry));
|
|
||||||
mAlertingSectioner.onEntriesUpdated(Arrays.asList(mEntry));
|
|
||||||
verify(mSilentHeaderController, times(2)).setClearSectionEnabled(eq(false));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNotClearableMinimizedSection() {
|
|
||||||
setSbnClearable(false);
|
|
||||||
when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(false);
|
|
||||||
setRankingAmbient(true);
|
|
||||||
mSilentSectioner.onEntriesUpdated(Arrays.asList(mEntry));
|
|
||||||
mMinimizedSectioner.onEntriesUpdated(Arrays.asList(mEntry));
|
|
||||||
mAlertingSectioner.onEntriesUpdated(Arrays.asList(mEntry));
|
|
||||||
verify(mSilentHeaderController, times(2)).setClearSectionEnabled(eq(false));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertInSection(NotificationEntry entry, NotifSectioner section) {
|
private void assertInSection(NotificationEntry entry, NotifSectioner section) {
|
||||||
for (NotifSectioner current: mSections) {
|
for (NotifSectioner current: mSections) {
|
||||||
if (current == section) {
|
if (current == section) {
|
||||||
|
|||||||
@@ -1,268 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2021 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.android.systemui.statusbar.notification.collection.coordinator
|
|
||||||
|
|
||||||
import android.os.UserHandle
|
|
||||||
import android.service.notification.StatusBarNotification
|
|
||||||
import androidx.test.filters.SmallTest
|
|
||||||
import com.android.keyguard.KeyguardUpdateMonitor
|
|
||||||
import com.android.systemui.SysuiTestCase
|
|
||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager
|
|
||||||
import com.android.systemui.statusbar.StatusBarState
|
|
||||||
import com.android.systemui.statusbar.notification.DynamicPrivacyController
|
|
||||||
import com.android.systemui.statusbar.notification.collection.ListEntry
|
|
||||||
import com.android.systemui.statusbar.notification.collection.NotifPipeline
|
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
|
||||||
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
|
|
||||||
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener
|
|
||||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator
|
|
||||||
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable
|
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController
|
|
||||||
import com.android.systemui.util.mockito.any
|
|
||||||
import com.android.systemui.util.mockito.mock
|
|
||||||
import com.android.systemui.util.mockito.withArgCaptor
|
|
||||||
import dagger.BindsInstance
|
|
||||||
import dagger.Component
|
|
||||||
import org.junit.Test
|
|
||||||
import org.mockito.Mockito.never
|
|
||||||
import org.mockito.Mockito.verify
|
|
||||||
import org.mockito.Mockito.`when` as whenever
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
class SensitiveContentCoordinatorTest : SysuiTestCase() {
|
|
||||||
|
|
||||||
val dynamicPrivacyController: DynamicPrivacyController = mock()
|
|
||||||
val lockscreenUserManager: NotificationLockscreenUserManager = mock()
|
|
||||||
val pipeline: NotifPipeline = mock()
|
|
||||||
val keyguardUpdateMonitor: KeyguardUpdateMonitor = mock()
|
|
||||||
val statusBarStateController: StatusBarStateController = mock()
|
|
||||||
val keyguardStateController: KeyguardStateController = mock()
|
|
||||||
|
|
||||||
val coordinator: SensitiveContentCoordinator =
|
|
||||||
DaggerTestSensitiveContentCoordinatorComponent
|
|
||||||
.factory()
|
|
||||||
.create(
|
|
||||||
dynamicPrivacyController,
|
|
||||||
lockscreenUserManager,
|
|
||||||
keyguardUpdateMonitor,
|
|
||||||
statusBarStateController,
|
|
||||||
keyguardStateController)
|
|
||||||
.coordinator
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun onDynamicPrivacyChanged_invokeInvalidationListener() {
|
|
||||||
coordinator.attach(pipeline)
|
|
||||||
val invalidator = withArgCaptor<Invalidator> {
|
|
||||||
verify(pipeline).addPreRenderInvalidator(capture())
|
|
||||||
}
|
|
||||||
val dynamicPrivacyListener = withArgCaptor<DynamicPrivacyController.Listener> {
|
|
||||||
verify(dynamicPrivacyController).addListener(capture())
|
|
||||||
}
|
|
||||||
|
|
||||||
val invalidationListener = mock<Pluggable.PluggableListener<Invalidator>>()
|
|
||||||
invalidator.setInvalidationListener(invalidationListener)
|
|
||||||
|
|
||||||
dynamicPrivacyListener.onDynamicPrivacyChanged()
|
|
||||||
|
|
||||||
verify(invalidationListener).onPluggableInvalidated(invalidator)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun onBeforeRenderList_deviceUnlocked_notifDoesNotNeedRedaction() {
|
|
||||||
coordinator.attach(pipeline)
|
|
||||||
val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> {
|
|
||||||
verify(pipeline).addOnBeforeRenderListListener(capture())
|
|
||||||
}
|
|
||||||
|
|
||||||
whenever(lockscreenUserManager.currentUserId).thenReturn(1)
|
|
||||||
whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false)
|
|
||||||
whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true)
|
|
||||||
whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
|
|
||||||
val entry = fakeNotification(1, false)
|
|
||||||
|
|
||||||
onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
|
|
||||||
|
|
||||||
verify(entry.representativeEntry!!).setSensitive(false, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun onBeforeRenderList_deviceUnlocked_notifWouldNeedRedaction() {
|
|
||||||
coordinator.attach(pipeline)
|
|
||||||
val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> {
|
|
||||||
verify(pipeline).addOnBeforeRenderListListener(capture())
|
|
||||||
}
|
|
||||||
|
|
||||||
whenever(lockscreenUserManager.currentUserId).thenReturn(1)
|
|
||||||
whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false)
|
|
||||||
whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true)
|
|
||||||
whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
|
|
||||||
val entry = fakeNotification(1, true)
|
|
||||||
|
|
||||||
onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
|
|
||||||
|
|
||||||
verify(entry.representativeEntry!!).setSensitive(false, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun onBeforeRenderList_deviceLocked_userAllowsPublicNotifs() {
|
|
||||||
coordinator.attach(pipeline)
|
|
||||||
val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> {
|
|
||||||
verify(pipeline).addOnBeforeRenderListListener(capture())
|
|
||||||
}
|
|
||||||
|
|
||||||
whenever(lockscreenUserManager.currentUserId).thenReturn(1)
|
|
||||||
whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
|
|
||||||
whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true)
|
|
||||||
whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
|
|
||||||
val entry = fakeNotification(1, false)
|
|
||||||
|
|
||||||
onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
|
|
||||||
|
|
||||||
verify(entry.representativeEntry!!).setSensitive(false, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun onBeforeRenderList_deviceLocked_userDisallowsPublicNotifs_notifDoesNotNeedRedaction() {
|
|
||||||
coordinator.attach(pipeline)
|
|
||||||
val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> {
|
|
||||||
verify(pipeline).addOnBeforeRenderListListener(capture())
|
|
||||||
}
|
|
||||||
|
|
||||||
whenever(lockscreenUserManager.currentUserId).thenReturn(1)
|
|
||||||
whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
|
|
||||||
whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
|
|
||||||
whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
|
|
||||||
val entry = fakeNotification(1, false)
|
|
||||||
|
|
||||||
onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
|
|
||||||
|
|
||||||
verify(entry.representativeEntry!!).setSensitive(false, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun onBeforeRenderList_deviceLocked_notifNeedsRedaction() {
|
|
||||||
coordinator.attach(pipeline)
|
|
||||||
val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> {
|
|
||||||
verify(pipeline).addOnBeforeRenderListListener(capture())
|
|
||||||
}
|
|
||||||
|
|
||||||
whenever(lockscreenUserManager.currentUserId).thenReturn(1)
|
|
||||||
whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
|
|
||||||
whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
|
|
||||||
whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
|
|
||||||
val entry = fakeNotification(1, true)
|
|
||||||
|
|
||||||
onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
|
|
||||||
|
|
||||||
verify(entry.representativeEntry!!).setSensitive(true, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun onBeforeRenderList_deviceDynamicallyUnlocked_notifNeedsRedaction() {
|
|
||||||
coordinator.attach(pipeline)
|
|
||||||
val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> {
|
|
||||||
verify(pipeline).addOnBeforeRenderListListener(capture())
|
|
||||||
}
|
|
||||||
|
|
||||||
whenever(lockscreenUserManager.currentUserId).thenReturn(1)
|
|
||||||
whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
|
|
||||||
whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
|
|
||||||
whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true)
|
|
||||||
val entry = fakeNotification(1, true)
|
|
||||||
|
|
||||||
onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
|
|
||||||
|
|
||||||
verify(entry.representativeEntry!!).setSensitive(false, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun onBeforeRenderList_deviceDynamicallyUnlocked_notifUserNeedsWorkChallenge() {
|
|
||||||
coordinator.attach(pipeline)
|
|
||||||
val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> {
|
|
||||||
verify(pipeline).addOnBeforeRenderListListener(capture())
|
|
||||||
}
|
|
||||||
|
|
||||||
whenever(lockscreenUserManager.currentUserId).thenReturn(1)
|
|
||||||
whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
|
|
||||||
whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
|
|
||||||
whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true)
|
|
||||||
whenever(lockscreenUserManager.needsSeparateWorkChallenge(2)).thenReturn(true)
|
|
||||||
|
|
||||||
val entry = fakeNotification(2, true)
|
|
||||||
|
|
||||||
onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
|
|
||||||
|
|
||||||
verify(entry.representativeEntry!!).setSensitive(true, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun onBeforeRenderList_deviceDynamicallyUnlocked_deviceBiometricBypassingLockScreen() {
|
|
||||||
coordinator.attach(pipeline)
|
|
||||||
val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> {
|
|
||||||
verify(pipeline).addOnBeforeRenderListListener(capture())
|
|
||||||
}
|
|
||||||
|
|
||||||
whenever(lockscreenUserManager.currentUserId).thenReturn(1)
|
|
||||||
whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
|
|
||||||
whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
|
|
||||||
whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true)
|
|
||||||
whenever(statusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD)
|
|
||||||
whenever(keyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing(any()))
|
|
||||||
.thenReturn(true)
|
|
||||||
|
|
||||||
val entry = fakeNotification(2, true)
|
|
||||||
|
|
||||||
onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
|
|
||||||
|
|
||||||
verify(entry.representativeEntry!!, never()).setSensitive(any(), any())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun fakeNotification(notifUserId: Int, needsRedaction: Boolean): ListEntry {
|
|
||||||
val mockUserHandle = mock<UserHandle>().apply {
|
|
||||||
whenever(identifier).thenReturn(notifUserId)
|
|
||||||
}
|
|
||||||
val mockSbn: StatusBarNotification = mock<StatusBarNotification>().apply {
|
|
||||||
whenever(user).thenReturn(mockUserHandle)
|
|
||||||
}
|
|
||||||
val mockEntry = mock<NotificationEntry>().apply {
|
|
||||||
whenever(sbn).thenReturn(mockSbn)
|
|
||||||
}
|
|
||||||
whenever(lockscreenUserManager.needsRedaction(mockEntry)).thenReturn(needsRedaction)
|
|
||||||
whenever(mockEntry.rowExists()).thenReturn(true)
|
|
||||||
return object : ListEntry("key", 0) {
|
|
||||||
override fun getRepresentativeEntry(): NotificationEntry = mockEntry
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@CoordinatorScope
|
|
||||||
@Component(modules = [SensitiveContentCoordinatorModule::class])
|
|
||||||
interface TestSensitiveContentCoordinatorComponent {
|
|
||||||
val coordinator: SensitiveContentCoordinator
|
|
||||||
|
|
||||||
@Component.Factory
|
|
||||||
interface Factory {
|
|
||||||
fun create(
|
|
||||||
@BindsInstance dynamicPrivacyController: DynamicPrivacyController,
|
|
||||||
@BindsInstance lockscreenUserManager: NotificationLockscreenUserManager,
|
|
||||||
@BindsInstance keyguardUpdateMonitor: KeyguardUpdateMonitor,
|
|
||||||
@BindsInstance statusBarStateController: StatusBarStateController,
|
|
||||||
@BindsInstance keyguardStateController: KeyguardStateController
|
|
||||||
): TestSensitiveContentCoordinatorComponent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.systemui.statusbar.notification.collection.coordinator
|
package com.android.systemui.statusbar.notification.collection.coordinator
|
||||||
|
|
||||||
|
import android.os.UserHandle
|
||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
import android.testing.TestableLooper.RunWithLooper
|
import android.testing.TestableLooper.RunWithLooper
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
@@ -43,6 +44,11 @@ import org.mockito.Mockito.`when` as whenever
|
|||||||
@RunWith(AndroidTestingRunner::class)
|
@RunWith(AndroidTestingRunner::class)
|
||||||
@RunWithLooper
|
@RunWithLooper
|
||||||
class StackCoordinatorTest : SysuiTestCase() {
|
class StackCoordinatorTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val NOTIF_USER_ID = 0
|
||||||
|
}
|
||||||
|
|
||||||
private lateinit var coordinator: StackCoordinator
|
private lateinit var coordinator: StackCoordinator
|
||||||
private lateinit var afterRenderListListener: OnAfterRenderListListener
|
private lateinit var afterRenderListListener: OnAfterRenderListListener
|
||||||
|
|
||||||
@@ -61,7 +67,10 @@ class StackCoordinatorTest : SysuiTestCase() {
|
|||||||
afterRenderListListener = withArgCaptor {
|
afterRenderListListener = withArgCaptor {
|
||||||
verify(pipeline).addOnAfterRenderListListener(capture())
|
verify(pipeline).addOnAfterRenderListListener(capture())
|
||||||
}
|
}
|
||||||
entry = NotificationEntryBuilder().setSection(section).build()
|
entry = NotificationEntryBuilder()
|
||||||
|
.setSection(section)
|
||||||
|
.setUser(UserHandle.of(NOTIF_USER_ID))
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -74,13 +83,31 @@ class StackCoordinatorTest : SysuiTestCase() {
|
|||||||
fun testSetNotificationStats_clearableAlerting() {
|
fun testSetNotificationStats_clearableAlerting() {
|
||||||
whenever(section.bucket).thenReturn(BUCKET_ALERTING)
|
whenever(section.bucket).thenReturn(BUCKET_ALERTING)
|
||||||
afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
|
afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
|
||||||
verify(stackController).setNotifStats(NotifStats(1, false, true, false, false))
|
verify(stackController)
|
||||||
|
.setNotifStats(
|
||||||
|
NotifStats(
|
||||||
|
1,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
setOf(NOTIF_USER_ID),
|
||||||
|
emptySet()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSetNotificationStats_clearableSilent() {
|
fun testSetNotificationStats_clearableSilent() {
|
||||||
whenever(section.bucket).thenReturn(BUCKET_SILENT)
|
whenever(section.bucket).thenReturn(BUCKET_SILENT)
|
||||||
afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
|
afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
|
||||||
verify(stackController).setNotifStats(NotifStats(1, false, false, false, true))
|
verify(stackController)
|
||||||
|
.setNotifStats(
|
||||||
|
NotifStats(
|
||||||
|
1,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
emptySet(),
|
||||||
|
setOf(NOTIF_USER_ID)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.systemui.statusbar.notification.icon;
|
package com.android.systemui.statusbar.notification.icon
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager
|
||||||
import android.app.Notification;
|
import android.app.Notification
|
||||||
import android.app.NotificationChannel
|
import android.app.NotificationChannel
|
||||||
import android.app.NotificationManager.IMPORTANCE_DEFAULT
|
import android.app.NotificationManager.IMPORTANCE_DEFAULT
|
||||||
import android.app.Person
|
import android.app.Person
|
||||||
@@ -27,11 +27,12 @@ import android.graphics.drawable.Drawable
|
|||||||
import android.graphics.drawable.Icon
|
import android.graphics.drawable.Icon
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import android.os.UserHandle
|
import android.os.UserHandle
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner
|
||||||
import androidx.test.InstrumentationRegistry
|
import androidx.test.InstrumentationRegistry
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.controls.controller.AuxiliaryPersistenceWrapperTest.Companion.any
|
import com.android.systemui.controls.controller.AuxiliaryPersistenceWrapperTest.Companion.any
|
||||||
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
|
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
|
||||||
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
|
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
|
||||||
@@ -40,7 +41,7 @@ import org.junit.Assert.assertEquals
|
|||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
import org.mockito.Mockito.`when`
|
import org.mockito.Mockito.`when`
|
||||||
import org.mockito.Mockito.anyInt
|
import org.mockito.Mockito.anyInt
|
||||||
@@ -48,15 +49,14 @@ import org.mockito.MockitoAnnotations
|
|||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidTestingRunner::class)
|
@RunWith(AndroidTestingRunner::class)
|
||||||
class IconManagerTest: SysuiTestCase() {
|
class IconManagerTest : SysuiTestCase() {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TEST_PACKAGE_NAME = "test";
|
private const val TEST_PACKAGE_NAME = "test"
|
||||||
private const val TEST_UID = 0;
|
private const val TEST_UID = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private var id = 0
|
private var id = 0
|
||||||
private val context = InstrumentationRegistry.getTargetContext();
|
private val context = InstrumentationRegistry.getTargetContext()
|
||||||
@Mock private lateinit var shortcut: ShortcutInfo
|
@Mock private lateinit var shortcut: ShortcutInfo
|
||||||
@Mock private lateinit var shortcutIc: Icon
|
@Mock private lateinit var shortcutIc: Icon
|
||||||
@Mock private lateinit var messageIc: Icon
|
@Mock private lateinit var messageIc: Icon
|
||||||
@@ -65,6 +65,7 @@ class IconManagerTest: SysuiTestCase() {
|
|||||||
@Mock private lateinit var drawable: Drawable
|
@Mock private lateinit var drawable: Drawable
|
||||||
@Mock private lateinit var row: ExpandableNotificationRow
|
@Mock private lateinit var row: ExpandableNotificationRow
|
||||||
|
|
||||||
|
@Mock private lateinit var notifLockscreenUserManager: NotificationLockscreenUserManager
|
||||||
@Mock private lateinit var notifCollection: CommonNotifCollection
|
@Mock private lateinit var notifCollection: CommonNotifCollection
|
||||||
@Mock private lateinit var launcherApps: LauncherApps
|
@Mock private lateinit var launcherApps: LauncherApps
|
||||||
|
|
||||||
@@ -83,13 +84,16 @@ class IconManagerTest: SysuiTestCase() {
|
|||||||
|
|
||||||
`when`(shortcut.icon).thenReturn(shortcutIc)
|
`when`(shortcut.icon).thenReturn(shortcutIc)
|
||||||
`when`(launcherApps.getShortcutIcon(shortcut)).thenReturn(shortcutIc)
|
`when`(launcherApps.getShortcutIcon(shortcut)).thenReturn(shortcutIc)
|
||||||
|
`when`(notifLockscreenUserManager.sensitiveNotifsNeedRedactionInPublic(TEST_UID))
|
||||||
|
.thenReturn(true)
|
||||||
|
|
||||||
iconManager = IconManager(notifCollection, launcherApps, iconBuilder)
|
iconManager =
|
||||||
|
IconManager(notifCollection, launcherApps, iconBuilder, notifLockscreenUserManager)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCreateIcons_importantConversation_shortcutIcon() {
|
fun testCreateIcons_importantConversation_shortcutIcon() {
|
||||||
val entry = notificationEntry(true, true, true)
|
val entry = notificationEntry()
|
||||||
entry?.channel?.isImportantConversation = true
|
entry?.channel?.isImportantConversation = true
|
||||||
entry?.let {
|
entry?.let {
|
||||||
iconManager.createIcons(it)
|
iconManager.createIcons(it)
|
||||||
@@ -99,7 +103,7 @@ class IconManagerTest: SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCreateIcons_importantConversation_messageIcon() {
|
fun testCreateIcons_importantConversation_messageIcon() {
|
||||||
val entry = notificationEntry(false, true, true)
|
val entry = notificationEntry(hasShortcut = false)
|
||||||
entry?.channel?.isImportantConversation = true
|
entry?.channel?.isImportantConversation = true
|
||||||
entry?.let {
|
entry?.let {
|
||||||
iconManager.createIcons(it)
|
iconManager.createIcons(it)
|
||||||
@@ -109,7 +113,7 @@ class IconManagerTest: SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCreateIcons_importantConversation_largeIcon() {
|
fun testCreateIcons_importantConversation_largeIcon() {
|
||||||
val entry = notificationEntry(false, false, true)
|
val entry = notificationEntry(hasShortcut = false, hasMessage = false)
|
||||||
entry?.channel?.isImportantConversation = true
|
entry?.channel?.isImportantConversation = true
|
||||||
entry?.let {
|
entry?.let {
|
||||||
iconManager.createIcons(it)
|
iconManager.createIcons(it)
|
||||||
@@ -119,7 +123,7 @@ class IconManagerTest: SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCreateIcons_importantConversation_smallIcon() {
|
fun testCreateIcons_importantConversation_smallIcon() {
|
||||||
val entry = notificationEntry(false, false, false)
|
val entry = notificationEntry(hasShortcut = false, hasMessage = false, hasLargeIcon = false)
|
||||||
entry?.channel?.isImportantConversation = true
|
entry?.channel?.isImportantConversation = true
|
||||||
entry?.let {
|
entry?.let {
|
||||||
iconManager.createIcons(it)
|
iconManager.createIcons(it)
|
||||||
@@ -129,7 +133,7 @@ class IconManagerTest: SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCreateIcons_notImportantConversation() {
|
fun testCreateIcons_notImportantConversation() {
|
||||||
val entry = notificationEntry(true, true, true)
|
val entry = notificationEntry()
|
||||||
entry?.let {
|
entry?.let {
|
||||||
iconManager.createIcons(it)
|
iconManager.createIcons(it)
|
||||||
}
|
}
|
||||||
@@ -138,8 +142,10 @@ class IconManagerTest: SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCreateIcons_sensitiveImportantConversation() {
|
fun testCreateIcons_sensitiveImportantConversation() {
|
||||||
val entry = notificationEntry(true, false, false)
|
val entry = notificationEntry(
|
||||||
entry?.setSensitive(true, true);
|
hasMessage = false,
|
||||||
|
hasLargeIcon = false,
|
||||||
|
hasSensitiveContent = true)
|
||||||
entry?.channel?.isImportantConversation = true
|
entry?.channel?.isImportantConversation = true
|
||||||
entry?.let {
|
entry?.let {
|
||||||
iconManager.createIcons(it)
|
iconManager.createIcons(it)
|
||||||
@@ -151,14 +157,17 @@ class IconManagerTest: SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testUpdateIcons_sensitivityChange() {
|
fun testUpdateIcons_sensitivityChange() {
|
||||||
val entry = notificationEntry(true, false, false)
|
val entry = notificationEntry(
|
||||||
|
hasMessage = false,
|
||||||
|
hasLargeIcon = false,
|
||||||
|
hasSensitiveContent = true)
|
||||||
entry?.channel?.isImportantConversation = true
|
entry?.channel?.isImportantConversation = true
|
||||||
entry?.setSensitive(true, true);
|
|
||||||
entry?.let {
|
entry?.let {
|
||||||
iconManager.createIcons(it)
|
iconManager.createIcons(it)
|
||||||
}
|
}
|
||||||
assertEquals(entry?.icons?.aodIcon?.sourceIcon, smallIc)
|
assertEquals(entry?.icons?.aodIcon?.sourceIcon, smallIc)
|
||||||
entry?.setSensitive(false, false);
|
`when`(notifLockscreenUserManager.sensitiveNotifsNeedRedactionInPublic(TEST_UID))
|
||||||
|
.thenReturn(false)
|
||||||
entry?.let {
|
entry?.let {
|
||||||
iconManager.updateIcons(it)
|
iconManager.updateIcons(it)
|
||||||
}
|
}
|
||||||
@@ -166,14 +175,19 @@ class IconManagerTest: SysuiTestCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun notificationEntry(
|
private fun notificationEntry(
|
||||||
hasShortcut: Boolean,
|
hasShortcut: Boolean = true,
|
||||||
hasMessage: Boolean,
|
hasMessage: Boolean = true,
|
||||||
hasLargeIcon: Boolean
|
hasLargeIcon: Boolean = true,
|
||||||
|
hasSensitiveContent: Boolean = false
|
||||||
): NotificationEntry? {
|
): NotificationEntry? {
|
||||||
val n = Notification.Builder(mContext, "id")
|
val n = Notification.Builder(mContext, "id")
|
||||||
.setSmallIcon(smallIc)
|
.setSmallIcon(smallIc)
|
||||||
.setContentTitle("Title")
|
.setContentTitle("Title")
|
||||||
.setContentText("Text")
|
.setContentText("Text")
|
||||||
|
.setVisibility(
|
||||||
|
if (hasSensitiveContent)
|
||||||
|
Notification.VISIBILITY_PRIVATE
|
||||||
|
else Notification.VISIBILITY_PUBLIC)
|
||||||
|
|
||||||
if (hasMessage) {
|
if (hasMessage) {
|
||||||
n.style = Notification.MessagingStyle("")
|
n.style = Notification.MessagingStyle("")
|
||||||
@@ -203,7 +217,6 @@ class IconManagerTest: SysuiTestCase() {
|
|||||||
|
|
||||||
val entry = builder.build()
|
val entry = builder.build()
|
||||||
entry.row = row
|
entry.row = row
|
||||||
entry.setSensitive(false, true);
|
|
||||||
return entry
|
return entry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGroupSummaryNotShowingIconWhenPublic() {
|
public void testGroupSummaryNotShowingIconWhenPublic() {
|
||||||
mGroupRow.setSensitive(true, true);
|
mGroupRow.setSensitive(true);
|
||||||
mGroupRow.setHideSensitiveForIntrinsicHeight(true);
|
mGroupRow.setHideSensitiveForIntrinsicHeight(true);
|
||||||
assertTrue(mGroupRow.isSummaryWithChildren());
|
assertTrue(mGroupRow.isSummaryWithChildren());
|
||||||
assertFalse(mGroupRow.isShowingIcon());
|
assertFalse(mGroupRow.isShowingIcon());
|
||||||
@@ -99,7 +99,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNotificationHeaderVisibleWhenAnimating() {
|
public void testNotificationHeaderVisibleWhenAnimating() {
|
||||||
mGroupRow.setSensitive(true, true);
|
mGroupRow.setSensitive(true);
|
||||||
mGroupRow.setHideSensitive(true, false, 0, 0);
|
mGroupRow.setHideSensitive(true, false, 0, 0);
|
||||||
mGroupRow.setHideSensitive(false, true, 0, 0);
|
mGroupRow.setHideSensitive(false, true, 0, 0);
|
||||||
assertEquals(View.VISIBLE, mGroupRow.getChildrenContainer().getVisibleWrapper()
|
assertEquals(View.VISIBLE, mGroupRow.getChildrenContainer().getVisibleWrapper()
|
||||||
@@ -130,7 +130,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
|
|||||||
public void testIconColorShouldBeUpdatedWhenSensitive() throws Exception {
|
public void testIconColorShouldBeUpdatedWhenSensitive() throws Exception {
|
||||||
ExpandableNotificationRow row = spy(mNotificationTestHelper.createRow(
|
ExpandableNotificationRow row = spy(mNotificationTestHelper.createRow(
|
||||||
FLAG_CONTENT_VIEW_ALL));
|
FLAG_CONTENT_VIEW_ALL));
|
||||||
row.setSensitive(true, true);
|
row.setSensitive(true);
|
||||||
row.setHideSensitive(true, false, 0, 0);
|
row.setHideSensitive(true, false, 0, 0);
|
||||||
verify(row).updateShelfIconColor();
|
verify(row).updateShelfIconColor();
|
||||||
}
|
}
|
||||||
@@ -214,7 +214,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testFeedback_noHeader() {
|
public void testFeedback_noHeader() {
|
||||||
// public notification is custom layout - no header
|
// public notification is custom layout - no header
|
||||||
mGroupRow.setSensitive(true, true);
|
mGroupRow.setSensitive(true);
|
||||||
mGroupRow.setOnFeedbackClickListener(null);
|
mGroupRow.setOnFeedbackClickListener(null);
|
||||||
mGroupRow.setFeedbackIcon(null);
|
mGroupRow.setFeedbackIcon(null);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ import com.android.systemui.statusbar.notification.collection.legacy.Notificatio
|
|||||||
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
|
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
|
||||||
import com.android.systemui.statusbar.notification.icon.IconBuilder;
|
import com.android.systemui.statusbar.notification.icon.IconBuilder;
|
||||||
import com.android.systemui.statusbar.notification.icon.IconManager;
|
import com.android.systemui.statusbar.notification.icon.IconManager;
|
||||||
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
|
|
||||||
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
|
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
|
||||||
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
|
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
|
||||||
import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
|
import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
|
||||||
@@ -132,7 +131,6 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
|
|||||||
@Mock private NotificationEntryListener mEntryListener;
|
@Mock private NotificationEntryListener mEntryListener;
|
||||||
@Mock private NotificationRowBinderImpl.BindRowCallback mBindCallback;
|
@Mock private NotificationRowBinderImpl.BindRowCallback mBindCallback;
|
||||||
@Mock private HeadsUpManager mHeadsUpManager;
|
@Mock private HeadsUpManager mHeadsUpManager;
|
||||||
@Mock private NotificationInterruptStateProvider mNotificationInterruptionStateProvider;
|
|
||||||
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
|
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
|
||||||
@Mock private NotificationGutsManager mGutsManager;
|
@Mock private NotificationGutsManager mGutsManager;
|
||||||
@Mock private NotificationRemoteInputManager mRemoteInputManager;
|
@Mock private NotificationRemoteInputManager mRemoteInputManager;
|
||||||
@@ -254,6 +252,7 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
|
|||||||
.thenAnswer((Answer<ExpandableNotificationRowController>) invocation ->
|
.thenAnswer((Answer<ExpandableNotificationRowController>) invocation ->
|
||||||
new ExpandableNotificationRowController(
|
new ExpandableNotificationRowController(
|
||||||
viewCaptor.getValue(),
|
viewCaptor.getValue(),
|
||||||
|
mLockscreenUserManager,
|
||||||
mock(ActivatableNotificationViewController.class),
|
mock(ActivatableNotificationViewController.class),
|
||||||
mock(RemoteInputViewSubcomponent.Factory.class),
|
mock(RemoteInputViewSubcomponent.Factory.class),
|
||||||
mock(MetricsLogger.class),
|
mock(MetricsLogger.class),
|
||||||
@@ -300,7 +299,8 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
|
|||||||
new IconManager(
|
new IconManager(
|
||||||
mEntryManager,
|
mEntryManager,
|
||||||
mock(LauncherApps.class),
|
mock(LauncherApps.class),
|
||||||
new IconBuilder(mContext)),
|
new IconBuilder(mContext),
|
||||||
|
mLockscreenUserManager),
|
||||||
mock(LowPriorityInflationHelper.class),
|
mock(LowPriorityInflationHelper.class),
|
||||||
mNotifPipelineFlags);
|
mNotifPipelineFlags);
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ import com.android.systemui.dump.DumpManager;
|
|||||||
import com.android.systemui.media.MediaFeatureFlag;
|
import com.android.systemui.media.MediaFeatureFlag;
|
||||||
import com.android.systemui.media.dialog.MediaOutputDialogFactory;
|
import com.android.systemui.media.dialog.MediaOutputDialogFactory;
|
||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||||
import com.android.systemui.statusbar.NotificationMediaManager;
|
import com.android.systemui.statusbar.NotificationMediaManager;
|
||||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||||
@@ -152,7 +153,8 @@ public class NotificationTestHelper {
|
|||||||
mIconManager = new IconManager(
|
mIconManager = new IconManager(
|
||||||
mock(CommonNotifCollection.class),
|
mock(CommonNotifCollection.class),
|
||||||
mock(LauncherApps.class),
|
mock(LauncherApps.class),
|
||||||
new IconBuilder(mContext));
|
new IconBuilder(mContext),
|
||||||
|
mock(NotificationLockscreenUserManager.class));
|
||||||
|
|
||||||
NotificationContentInflater contentBinder = new NotificationContentInflater(
|
NotificationContentInflater contentBinder = new NotificationContentInflater(
|
||||||
mock(NotifRemoteViewCache.class),
|
mock(NotifRemoteViewCache.class),
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import com.android.systemui.plugins.DarkIconDispatcher;
|
|||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
import com.android.systemui.statusbar.CommandQueue;
|
import com.android.systemui.statusbar.CommandQueue;
|
||||||
import com.android.systemui.statusbar.HeadsUpStatusBarView;
|
import com.android.systemui.statusbar.HeadsUpStatusBarView;
|
||||||
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||||
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
|
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
|
||||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
||||||
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
|
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
|
||||||
@@ -57,9 +58,12 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
|
|||||||
|
|
||||||
private final NotificationStackScrollLayoutController mStackScrollerController =
|
private final NotificationStackScrollLayoutController mStackScrollerController =
|
||||||
mock(NotificationStackScrollLayoutController.class);
|
mock(NotificationStackScrollLayoutController.class);
|
||||||
private final NotificationPanelViewController mPanelView =
|
private final NotificationPanelViewController mPanelViewController =
|
||||||
mock(NotificationPanelViewController.class);
|
mock(NotificationPanelViewController.class);
|
||||||
private final DarkIconDispatcher mDarkIconDispatcher = mock(DarkIconDispatcher.class);
|
private final DarkIconDispatcher mDarkIconDispatcher = mock(DarkIconDispatcher.class);
|
||||||
|
private final NotificationLockscreenUserManager mLockscreenUserManager =
|
||||||
|
mock(NotificationLockscreenUserManager.class);
|
||||||
|
|
||||||
private HeadsUpAppearanceController mHeadsUpAppearanceController;
|
private HeadsUpAppearanceController mHeadsUpAppearanceController;
|
||||||
private ExpandableNotificationRow mFirst;
|
private ExpandableNotificationRow mFirst;
|
||||||
private HeadsUpStatusBarView mHeadsUpStatusBarView;
|
private HeadsUpStatusBarView mHeadsUpStatusBarView;
|
||||||
@@ -93,12 +97,13 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
|
|||||||
mHeadsUpManager,
|
mHeadsUpManager,
|
||||||
mStatusbarStateController,
|
mStatusbarStateController,
|
||||||
mBypassController,
|
mBypassController,
|
||||||
|
mLockscreenUserManager,
|
||||||
mWakeUpCoordinator,
|
mWakeUpCoordinator,
|
||||||
mDarkIconDispatcher,
|
mDarkIconDispatcher,
|
||||||
mKeyguardStateController,
|
mKeyguardStateController,
|
||||||
mCommandQueue,
|
mCommandQueue,
|
||||||
mStackScrollerController,
|
mStackScrollerController,
|
||||||
mPanelView,
|
mPanelViewController,
|
||||||
mHeadsUpStatusBarView,
|
mHeadsUpStatusBarView,
|
||||||
new Clock(mContext, null),
|
new Clock(mContext, null),
|
||||||
Optional.of(mOperatorNameView));
|
Optional.of(mOperatorNameView));
|
||||||
@@ -175,12 +180,13 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
|
|||||||
mHeadsUpManager,
|
mHeadsUpManager,
|
||||||
mStatusbarStateController,
|
mStatusbarStateController,
|
||||||
mBypassController,
|
mBypassController,
|
||||||
|
mLockscreenUserManager,
|
||||||
mWakeUpCoordinator,
|
mWakeUpCoordinator,
|
||||||
mDarkIconDispatcher,
|
mDarkIconDispatcher,
|
||||||
mKeyguardStateController,
|
mKeyguardStateController,
|
||||||
mCommandQueue,
|
mCommandQueue,
|
||||||
mStackScrollerController,
|
mStackScrollerController,
|
||||||
mPanelView,
|
mPanelViewController,
|
||||||
mHeadsUpStatusBarView,
|
mHeadsUpStatusBarView,
|
||||||
new Clock(mContext, null),
|
new Clock(mContext, null),
|
||||||
Optional.empty());
|
Optional.empty());
|
||||||
@@ -193,15 +199,15 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
|
|||||||
public void testDestroy() {
|
public void testDestroy() {
|
||||||
reset(mHeadsUpManager);
|
reset(mHeadsUpManager);
|
||||||
reset(mDarkIconDispatcher);
|
reset(mDarkIconDispatcher);
|
||||||
reset(mPanelView);
|
reset(mPanelViewController);
|
||||||
reset(mStackScrollerController);
|
reset(mStackScrollerController);
|
||||||
|
|
||||||
mHeadsUpAppearanceController.onViewDetached();
|
mHeadsUpAppearanceController.onViewDetached();
|
||||||
|
|
||||||
verify(mHeadsUpManager).removeListener(any());
|
verify(mHeadsUpManager).removeListener(any());
|
||||||
verify(mDarkIconDispatcher).removeDarkReceiver((DarkIconDispatcher.DarkReceiver) any());
|
verify(mDarkIconDispatcher).removeDarkReceiver((DarkIconDispatcher.DarkReceiver) any());
|
||||||
verify(mPanelView).removeTrackingHeadsUpListener(any());
|
verify(mPanelViewController).removeTrackingHeadsUpListener(any());
|
||||||
verify(mPanelView).setHeadsUpAppearanceController(isNull());
|
verify(mPanelViewController).setHeadsUpAppearanceController(isNull());
|
||||||
verify(mStackScrollerController).removeOnExpandedHeightChangedListener(any());
|
verify(mStackScrollerController).removeOnExpandedHeightChangedListener(any());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user