Don't show "Clear All" w/ redacted notifs
The logic that determined when to show the Clear All Silent button in the
Silent notification header was occurring when the Silent (and Minimized)
sections update. At this time, there was no up-to-date information about
whether or not the notification has senstive content
(SensitiveContentCoordinator occurs later in the pipeline), and no
information about whether or not sensitive content can even be shown or
must be redacted (handled by NotificationStackScrollLayoutController).
Additionally, the visibility of the Clear All button in the shade footer
wasn't being adjusted at all under the new pipeline.
To remedy this, the following changes were made in this CL:
1. `boolean NotificationEntry#isSensitive()` has been dismantled. Rather
than relying on some separate code to properly set this value at some
point, instead the concept of "Sensitive Content" is derived directly
from the SBN + Ranking, and is kept separate from the state of the
user's settings, as well as the state of the lockscreen (whether we
would currently need to redact).
2. NotificationLockscreenUserMananger is the de-facto place for tracking
and querying redaction state. This includes checking if the user's
settings *would* require redaction (#needsRedactionInPublic), and
whether a user is actually public (#isLockscreenPublicMode).
3. In order to keep clients in sync, a new observable interface is
exposed on NotificationLockscreenUserManager that clients can use to be
notified when to requery #needsRedactionInPublic, due to user settings
changes. This replaces NotificationEntry#OnSensitivityChangedListener
4. SensitiveContentCoordinator has been removed entirely; the pipeline
no longer needs to invoke NotificationEntry#setSenstive, since it no
longer exists.
5. NotifStats has been updated to include additional information
extracted from the NotifCollection necessary to dynamically query for
redaction in the View layer, without needed to re-process the entire
list; specifically, we track a Set of users that currently have
sensitive notifications in the shade. This set is tested against the
user's settings (tracked separately from the pipeline in
NotifLockscreenUserManager).
Test: atest
Test: 1. Turn on notification redaction (no sensitive contents on lockscreen)
2. Receive a silent sensitive notification
3. Lock the device
4. Double tap camera
5. expand shade
Observe: Clear all hidden in footer and in silent header
Fixes: 213443266
Fixes: 230581048
Change-Id: Ibc66576d28a48f7c82cad875ed2dcb57a7b23f10
Merged-In: Ibc66576d28a48f7c82cad875ed2dcb57a7b23f10
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;
|
||||||
@@ -1560,6 +1559,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) {
|
||||||
@@ -2644,9 +2644,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
|
||||||
@@ -2736,7 +2735,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2745,7 +2752,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() {
|
||||||
@@ -3509,10 +3516,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);
|
||||||
@@ -3538,8 +3563,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()) {
|
||||||
|
|||||||
@@ -31,7 +31,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;
|
||||||
@@ -3916,10 +3915,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