Merge "Trigger re-inflate when sensitive setting changes" into tm-dev

This commit is contained in:
TreeHugger Robot
2022-06-03 23:31:43 +00:00
committed by Android (Google) Code Review
7 changed files with 123 additions and 9 deletions

View File

@@ -89,6 +89,18 @@ public interface NotificationLockscreenUserManager {
*/ */
boolean userAllowsNotificationsInPublic(int userId); boolean userAllowsNotificationsInPublic(int userId);
/**
* Adds a {@link NotificationStateChangedListener} to be notified of any state changes that
* would affect presentation of notifications.
*/
void addNotificationStateChangedListener(NotificationStateChangedListener listener);
/**
* Removes a {@link NotificationStateChangedListener} that was previously registered with
* {@link #addNotificationStateChangedListener(NotificationStateChangedListener)}.
*/
void removeNotificationStateChangedListener(NotificationStateChangedListener listener);
/** Notified when the current user changes. */ /** Notified when the current user changes. */
interface UserChangedListener { interface UserChangedListener {
default void onUserChanged(int userId) {} default void onUserChanged(int userId) {}
@@ -100,4 +112,12 @@ public interface NotificationLockscreenUserManager {
interface KeyguardNotificationSuppressor { interface KeyguardNotificationSuppressor {
boolean shouldSuppressOnKeyguard(NotificationEntry entry); boolean shouldSuppressOnKeyguard(NotificationEntry entry);
} }
/**
* Notified when any state pertaining to Notifications has changed; any methods pertaining to
* notifications should be re-queried.
*/
interface NotificationStateChangedListener {
void onNotificationStateChanged();
}
} }

View File

@@ -60,6 +60,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;
@@ -110,6 +111,8 @@ public class NotificationLockscreenUserManagerImpl implements
protected KeyguardManager mKeyguardManager; protected KeyguardManager mKeyguardManager;
private int mState = StatusBarState.SHADE; private int mState = StatusBarState.SHADE;
private List<KeyguardNotificationSuppressor> mKeyguardSuppressors = new ArrayList<>(); private List<KeyguardNotificationSuppressor> mKeyguardSuppressors = new ArrayList<>();
private final ListenerSet<NotificationStateChangedListener> mNotifStateChangedListeners =
new ListenerSet<>();
protected final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() { protected final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() {
@Override @Override
@@ -121,6 +124,8 @@ public class NotificationLockscreenUserManagerImpl implements
mUsersAllowingPrivateNotifications.clear(); mUsersAllowingPrivateNotifications.clear();
updateLockscreenNotificationSetting(); updateLockscreenNotificationSetting();
getEntryManager().updateNotifications("ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED"); getEntryManager().updateNotifications("ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED");
// TODO(b/231976036): Consolidate pipeline invalidations related to this event
// notifyNotificationStateChanged();
} }
} }
}; };
@@ -254,6 +259,7 @@ public class NotificationLockscreenUserManagerImpl implements
updateLockscreenNotificationSetting(); updateLockscreenNotificationSetting();
getEntryManager().updateNotifications("LOCK_SCREEN_SHOW_NOTIFICATIONS," getEntryManager().updateNotifications("LOCK_SCREEN_SHOW_NOTIFICATIONS,"
+ " or LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS change"); + " or LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS change");
notifyNotificationStateChanged();
} }
}; };
@@ -264,6 +270,8 @@ public class NotificationLockscreenUserManagerImpl implements
if (mDeviceProvisionedController.isDeviceProvisioned()) { if (mDeviceProvisionedController.isDeviceProvisioned()) {
getEntryManager().updateNotifications("LOCK_SCREEN_ALLOW_REMOTE_INPUT" getEntryManager().updateNotifications("LOCK_SCREEN_ALLOW_REMOTE_INPUT"
+ " or ZEN_MODE change"); + " or ZEN_MODE change");
// TODO(b/231976036): Consolidate pipeline invalidations related to this event
// notifyNotificationStateChanged();
} }
} }
}; };
@@ -651,6 +659,8 @@ public class NotificationLockscreenUserManagerImpl implements
mUsersWithSeparateWorkChallenge.put(userId, needsSeparateChallenge); mUsersWithSeparateWorkChallenge.put(userId, needsSeparateChallenge);
} }
getEntryManager().updateNotifications("NotificationLockscreenUserManager.updatePublicMode"); getEntryManager().updateNotifications("NotificationLockscreenUserManager.updatePublicMode");
// TODO(b/234738798): Migrate KeyguardNotificationVisibilityProvider to use this listener
// notifyNotificationStateChanged();
} }
@Override @Override
@@ -668,6 +678,22 @@ public class NotificationLockscreenUserManagerImpl implements
mListeners.remove(listener); mListeners.remove(listener);
} }
@Override
public void addNotificationStateChangedListener(NotificationStateChangedListener listener) {
mNotifStateChangedListeners.addIfAbsent(listener);
}
@Override
public void removeNotificationStateChangedListener(NotificationStateChangedListener listener) {
mNotifStateChangedListeners.remove(listener);
}
private void notifyNotificationStateChanged() {
for (NotificationStateChangedListener listener : mNotifStateChangedListeners) {
listener.onNotificationStateChanged();
}
}
// public void updatePublicMode() { // public void updatePublicMode() {
// //TODO: I think there may be a race condition where mKeyguardViewManager.isShowing() returns // //TODO: I think there may be a race condition where mKeyguardViewManager.isShowing() returns
// // false when it should be true. Therefore, if we are not on the SHADE, don't even bother // // false when it should be true. Therefore, if we are not on the SHADE, don't even bother

View File

@@ -147,6 +147,7 @@ public class PreparationCoordinator implements Coordinator {
@Override @Override
public void attach(NotifPipeline pipeline) { public void attach(NotifPipeline pipeline) {
mNotifErrorManager.addInflationErrorListener(mInflationErrorListener); mNotifErrorManager.addInflationErrorListener(mInflationErrorListener);
mAdjustmentProvider.addDirtyListener(mNotifInflatingFilter::invalidateList);
pipeline.addCollectionListener(mNotifCollectionListener); pipeline.addCollectionListener(mNotifCollectionListener);
// Inflate after grouping/sorting since that affects what views to inflate. // Inflate after grouping/sorting since that affects what views to inflate.

View File

@@ -31,7 +31,8 @@ class NotifUiAdjustment internal constructor(
val smartActions: List<Notification.Action>, val smartActions: List<Notification.Action>,
val smartReplies: List<CharSequence>, val smartReplies: List<CharSequence>,
val isConversation: Boolean, val isConversation: Boolean,
val isMinimized: Boolean val isMinimized: Boolean,
val needsRedaction: Boolean,
) { ) {
companion object { companion object {
@JvmStatic @JvmStatic
@@ -42,6 +43,7 @@ class NotifUiAdjustment internal constructor(
oldAdjustment === newAdjustment -> false oldAdjustment === newAdjustment -> false
oldAdjustment.isConversation != newAdjustment.isConversation -> true oldAdjustment.isConversation != newAdjustment.isConversation -> true
oldAdjustment.isMinimized != newAdjustment.isMinimized -> true oldAdjustment.isMinimized != newAdjustment.isMinimized -> true
oldAdjustment.needsRedaction != newAdjustment.needsRedaction -> true
areDifferent(oldAdjustment.smartActions, newAdjustment.smartActions) -> true areDifferent(oldAdjustment.smartActions, newAdjustment.smartActions) -> true
newAdjustment.smartReplies != oldAdjustment.smartReplies -> true newAdjustment.smartReplies != oldAdjustment.smartReplies -> true
else -> false else -> false

View File

@@ -17,9 +17,11 @@
package com.android.systemui.statusbar.notification.collection.inflation package com.android.systemui.statusbar.notification.collection.inflation
import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.notification.SectionClassifier import com.android.systemui.statusbar.notification.SectionClassifier
import com.android.systemui.statusbar.notification.collection.GroupEntry import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.util.ListenerSet
import javax.inject.Inject import javax.inject.Inject
/** /**
@@ -27,9 +29,30 @@ import javax.inject.Inject
* to ensure that notifications are reinflated when ranking-derived information changes. * to ensure that notifications are reinflated when ranking-derived information changes.
*/ */
@SysUISingleton @SysUISingleton
open class NotifUiAdjustmentProvider @Inject constructor( class NotifUiAdjustmentProvider @Inject constructor(
private val sectionClassifier: SectionClassifier private val lockscreenUserManager: NotificationLockscreenUserManager,
private val sectionClassifier: SectionClassifier,
) { ) {
private val dirtyListeners = ListenerSet<Runnable>()
fun addDirtyListener(listener: Runnable) {
if (dirtyListeners.isEmpty()) {
lockscreenUserManager.addNotificationStateChangedListener(notifStateChangedListener)
}
dirtyListeners.addIfAbsent(listener)
}
fun removeDirtyListener(listener: Runnable) {
dirtyListeners.remove(listener)
if (dirtyListeners.isEmpty()) {
lockscreenUserManager.removeNotificationStateChangedListener(notifStateChangedListener)
}
}
private val notifStateChangedListener =
NotificationLockscreenUserManager.NotificationStateChangedListener {
dirtyListeners.forEach(Runnable::run)
}
private fun isEntryMinimized(entry: NotificationEntry): Boolean { private fun isEntryMinimized(entry: NotificationEntry): Boolean {
val section = entry.section ?: error("Entry must have a section to determine if minimized") val section = entry.section ?: error("Entry must have a section to determine if minimized")
@@ -42,14 +65,15 @@ open class NotifUiAdjustmentProvider @Inject constructor(
/** /**
* Returns a adjustment object for the given entry. This can be compared to a previous instance * Returns a adjustment object for the given entry. This can be compared to a previous instance
* from the same notification using [NotifUiAdjustment.needReinflate] to determine if it * from the same notification using [NotifUiAdjustment.needReinflate] to determine if it should
* should be reinflated. * be reinflated.
*/ */
fun calculateAdjustment(entry: NotificationEntry) = NotifUiAdjustment( fun calculateAdjustment(entry: NotificationEntry) = NotifUiAdjustment(
key = entry.key, key = entry.key,
smartActions = entry.ranking.smartActions, smartActions = entry.ranking.smartActions,
smartReplies = entry.ranking.smartReplies, smartReplies = entry.ranking.smartReplies,
isConversation = entry.ranking.isConversation, isConversation = entry.ranking.isConversation,
isMinimized = isEntryMinimized(entry) isMinimized = isEntryMinimized(entry),
needsRedaction = lockscreenUserManager.needsRedaction(entry),
) )
} }

View File

@@ -40,6 +40,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.RankingBuilder; import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.notification.SectionClassifier; import com.android.systemui.statusbar.notification.SectionClassifier;
import com.android.systemui.statusbar.notification.collection.GroupEntry; import com.android.systemui.statusbar.notification.collection.GroupEntry;
@@ -95,10 +96,11 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
@Mock private NotifPipeline mNotifPipeline; @Mock private NotifPipeline mNotifPipeline;
@Mock private IStatusBarService mService; @Mock private IStatusBarService mService;
@Mock private BindEventManagerImpl mBindEventManagerImpl; @Mock private BindEventManagerImpl mBindEventManagerImpl;
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
@Spy private FakeNotifInflater mNotifInflater = new FakeNotifInflater(); @Spy private FakeNotifInflater mNotifInflater = new FakeNotifInflater();
private final SectionClassifier mSectionClassifier = new SectionClassifier(); private final SectionClassifier mSectionClassifier = new SectionClassifier();
private final NotifUiAdjustmentProvider mAdjustmentProvider =
new NotifUiAdjustmentProvider(mSectionClassifier); private NotifUiAdjustmentProvider mAdjustmentProvider;
@NonNull @NonNull
private NotificationEntryBuilder getNotificationEntryBuilder() { private NotificationEntryBuilder getNotificationEntryBuilder() {
@@ -108,7 +110,8 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mAdjustmentProvider =
new NotifUiAdjustmentProvider(mLockscreenUserManager, mSectionClassifier);
mEntry = getNotificationEntryBuilder().setParent(ROOT_ENTRY).build(); mEntry = getNotificationEntryBuilder().setParent(ROOT_ENTRY).build();
mInflationError = new Exception(TEST_MESSAGE); mInflationError = new Exception(TEST_MESSAGE);
mErrorManager = new NotifInflationErrorManager(); mErrorManager = new NotifInflationErrorManager();

View File

@@ -0,0 +1,38 @@
package com.android.systemui.statusbar.notification.collection.inflation
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.notification.SectionClassifier
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.withArgCaptor
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.verify
@SmallTest
@RunWith(AndroidTestingRunner::class)
@RunWithLooper
class NotifUiAdjustmentProviderTest : SysuiTestCase() {
private val lockscreenUserManager: NotificationLockscreenUserManager = mock()
private val sectionClassifier: SectionClassifier = mock()
private val adjustmentProvider = NotifUiAdjustmentProvider(
lockscreenUserManager,
sectionClassifier,
)
@Test
fun notifLockscreenStateChangeWillNotifDirty() {
val dirtyListener = mock<Runnable>()
adjustmentProvider.addDirtyListener(dirtyListener)
val notifLocksreenStateChangeListener =
withArgCaptor<NotificationLockscreenUserManager.NotificationStateChangedListener> {
verify(lockscreenUserManager).addNotificationStateChangedListener(capture())
}
notifLocksreenStateChangeListener.onNotificationStateChanged()
verify(dirtyListener).run();
}
}