summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author mpodolian <mpodolian@google.com> 2024-05-03 14:48:06 +0100
committer mpodolian <mpodolian@google.com> 2024-05-09 09:59:55 +0100
commit318236a5280b0135e0a39dcea226238aab0a7f3c (patch)
tree674241eaf62cd242923d4b1b0959f896412455a2
parent4152bc7ec0f316a8587b31874e9b989d98c62668 (diff)
Fixed issue with notification bubble icon interaction on the lock screen
Updated logic to perform bubble action only after user unlocks the device. Test: StatusBarNotificationActivityStarterTest Flag: NA Fixes: 269059797 Change-Id: I08a41d2f338b6a4705665c7216960c68597b1123
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java52
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java52
5 files changed, 117 insertions, 14 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.java
index 0c341cc92f83..ec3c7d0d6de4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.java
@@ -27,6 +27,9 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
* (e.g. clicking on a notification, tapping on the settings icon in the notification guts)
*/
public interface NotificationActivityStarter {
+ /** Called when the user clicks on the notification bubble icon. */
+ void onNotificationBubbleIconClicked(NotificationEntry entry);
+
/** Called when the user clicks on the surface of a notification. */
void onNotificationClicked(NotificationEntry entry, ExpandableNotificationRow row);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java
index d10fac6ea3fc..6487d55197e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClicker.java
@@ -117,11 +117,14 @@ public final class NotificationClicker implements View.OnClickListener {
Notification notification = sbn.getNotification();
if (notification.contentIntent != null || notification.fullScreenIntent != null
|| row.getEntry().isBubble()) {
+ row.setBubbleClickListener(v ->
+ mNotificationActivityStarter.onNotificationBubbleIconClicked(row.getEntry()));
row.setOnClickListener(this);
row.setOnDragSuccessListener(mOnDragSuccessListener);
} else {
row.setOnClickListener(null);
row.setOnDragSuccessListener(null);
+ row.setBubbleClickListener(null);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 5e3df7b5e60f..23c0a0db04d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -375,6 +375,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
};
private OnClickListener mOnClickListener;
+ @Nullable
+ private OnClickListener mBubbleClickListener;
private OnDragSuccessListener mOnDragSuccessListener;
private boolean mHeadsupDisappearRunning;
private View mChildAfterViewWhenDismissed;
@@ -1234,14 +1236,19 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
/**
* The click listener for the bubble button.
*/
+ @Nullable
public View.OnClickListener getBubbleClickListener() {
- return v -> {
- if (mBubblesManagerOptional.isPresent()) {
- mBubblesManagerOptional.get()
- .onUserChangedBubble(mEntry, !mEntry.isBubble() /* createBubble */);
- }
- mHeadsUpManager.removeNotification(mEntry.getKey(), true /* releaseImmediately */);
- };
+ return mBubbleClickListener;
+ }
+
+ /**
+ * Sets the click listener for the bubble button.
+ */
+ public void setBubbleClickListener(@Nullable OnClickListener l) {
+ mBubbleClickListener = l;
+ // ensure listener is passed to the content views
+ mPrivateLayout.updateBubbleButton(mEntry);
+ mPublicLayout.updateBubbleButton(mEntry);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index e1a7f22a913a..e92058bf034a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -96,6 +96,20 @@ import javax.inject.Inject;
@SysUISingleton
public class StatusBarNotificationActivityStarter implements NotificationActivityStarter {
+ /**
+ * Helps to avoid recalculation of values provided to
+ * {@link #onDismiss(PendingIntent, boolean, boolean, boolean)}} method
+ */
+ private interface OnKeyguardDismissedAction {
+ /**
+ * Invoked when keyguard is dismissed
+ *
+ * @return is used as return value for {@link ActivityStarter.OnDismissAction#onDismiss()}
+ */
+ boolean onDismiss(PendingIntent intent, boolean isActivityIntent, boolean animate,
+ boolean showOverTheLockScreen);
+ }
+
private final Context mContext;
private final int mDisplayId;
@@ -207,6 +221,30 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
}
/**
+ * Called when the user clicks on the notification bubble icon.
+ *
+ * @param entry notification that bubble icon was clicked
+ */
+ @Override
+ public void onNotificationBubbleIconClicked(NotificationEntry entry) {
+ Runnable action = () -> {
+ mBubblesManagerOptional.ifPresent(bubblesManager ->
+ bubblesManager.onUserChangedBubble(entry, !entry.isBubble()));
+ mHeadsUpManager.removeNotification(entry.getKey(), /* releaseImmediately= */ true);
+ };
+ if (entry.isBubble()) {
+ // entry is being un-bubbled, no need to unlock
+ action.run();
+ } else {
+ performActionAfterKeyguardDismissed(entry,
+ (intent, isActivityIntent, animate, showOverTheLockScreen) -> {
+ action.run();
+ return false;
+ });
+ }
+ }
+
+ /**
* Called when a notification is clicked.
*
* @param entry notification that was clicked
@@ -217,7 +255,15 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mLogger.logStartingActivityFromClick(entry, row.isHeadsUpState(),
mKeyguardStateController.isVisible(),
mNotificationShadeWindowController.getPanelExpanded());
+ OnKeyguardDismissedAction action =
+ (intent, isActivityIntent, animate, showOverTheLockScreen) ->
+ performActionOnKeyguardDismissed(entry, row, intent, isActivityIntent,
+ animate, showOverTheLockScreen);
+ performActionAfterKeyguardDismissed(entry, action);
+ }
+ private void performActionAfterKeyguardDismissed(NotificationEntry entry,
+ OnKeyguardDismissedAction action) {
if (mRemoteInputManager.isRemoteInputActive(entry)) {
// We have an active remote input typed and the user clicked on the notification.
// this was probably unintentional, so we're closing the edit text instead.
@@ -251,8 +297,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
ActivityStarter.OnDismissAction postKeyguardAction = new ActivityStarter.OnDismissAction() {
@Override
public boolean onDismiss() {
- return handleNotificationClickAfterKeyguardDismissed(
- entry, row, intent, isActivityIntent, animate, showOverLockscreen);
+ return action.onDismiss(intent, isActivityIntent, animate, showOverLockscreen);
}
@Override
@@ -271,7 +316,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
}
}
- private boolean handleNotificationClickAfterKeyguardDismissed(
+ private boolean performActionOnKeyguardDismissed(
NotificationEntry entry,
ExpandableNotificationRow row,
PendingIntent intent,
@@ -282,7 +327,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
final Runnable runnable = () -> handleNotificationClickAfterPanelCollapsed(
entry, row, intent, isActivityIntent, animate);
-
if (showOverLockscreen) {
mShadeController.addPostCollapseAction(runnable);
mShadeController.collapseShade(true /* animate */);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index 127a3d7b208b..269510e0b4b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -168,6 +168,8 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
private FakePowerRepository mPowerRepository;
@Mock
private UserTracker mUserTracker;
+ @Mock
+ private HeadsUpManager mHeadsUpManager;
private final FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
private ExpandableNotificationRow mNotificationRow;
private ExpandableNotificationRow mBubbleNotificationRow;
@@ -222,13 +224,12 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
mScreenOffAnimationController,
mStatusBarStateController).getPowerInteractor();
- HeadsUpManager headsUpManager = mock(HeadsUpManager.class);
NotificationLaunchAnimatorControllerProvider notificationAnimationProvider =
new NotificationLaunchAnimatorControllerProvider(
new NotificationLaunchAnimationInteractor(
new NotificationLaunchAnimationRepository()),
mock(NotificationListContainer.class),
- headsUpManager,
+ mHeadsUpManager,
mJankMonitor);
mNotificationActivityStarter =
new StatusBarNotificationActivityStarter(
@@ -237,7 +238,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
mHandler,
mUiBgExecutor,
mVisibilityProvider,
- headsUpManager,
+ mHeadsUpManager,
mActivityStarter,
mCommandQueue,
mClickNotifier,
@@ -417,6 +418,51 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
}
@Test
+ public void testOnNotificationBubbleIconClicked_unbubble_keyGuardShowing()
+ throws RemoteException {
+ NotificationEntry entry = mBubbleNotificationRow.getEntry();
+ StatusBarNotification sbn = entry.getSbn();
+
+ // Given
+ sbn.getNotification().contentIntent = mContentIntent;
+ when(mKeyguardStateController.isShowing()).thenReturn(true);
+ when(mKeyguardStateController.isOccluded()).thenReturn(true);
+
+ // When
+ mNotificationActivityStarter.onNotificationBubbleIconClicked(entry);
+
+ // Then
+ verify(mBubblesManager).onUserChangedBubble(entry, false);
+
+ verify(mHeadsUpManager).removeNotification(entry.getKey(), true);
+
+ verifyNoMoreInteractions(mContentIntent);
+ verifyNoMoreInteractions(mShadeController);
+ }
+
+ @Test
+ public void testOnNotificationBubbleIconClicked_bubble_keyGuardShowing() {
+ NotificationEntry entry = mNotificationRow.getEntry();
+ StatusBarNotification sbn = entry.getSbn();
+
+ // Given
+ sbn.getNotification().contentIntent = mContentIntent;
+ when(mKeyguardStateController.isShowing()).thenReturn(true);
+ when(mKeyguardStateController.isOccluded()).thenReturn(true);
+
+ // When
+ mNotificationActivityStarter.onNotificationBubbleIconClicked(entry);
+
+ // Then
+ verify(mBubblesManager).onUserChangedBubble(entry, true);
+
+ verify(mHeadsUpManager).removeNotification(entry.getKey(), true);
+
+ verify(mContentIntent, atLeastOnce()).isActivity();
+ verifyNoMoreInteractions(mContentIntent);
+ }
+
+ @Test
public void testOnFullScreenIntentWhenDozing_wakeUpDevice() {
// GIVEN entry that can has a full screen intent that can show
PendingIntent fullScreenIntent = PendingIntent.getActivity(mContext, 1,