diff options
3 files changed, 124 insertions, 8 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt index 692a9977c364..4ab78aab372d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt @@ -1,8 +1,8 @@ package com.android.systemui.statusbar +import android.app.Flags.lifetimeExtensionRefactor import android.app.Notification import android.os.RemoteException -import android.util.Log import com.android.internal.statusbar.IStatusBarService import com.android.internal.statusbar.NotificationVisibility import com.android.systemui.dagger.SysUISingleton @@ -58,9 +58,14 @@ public class NotificationClickNotifier @Inject constructor( } catch (e: RemoteException) { // nothing } + if (lifetimeExtensionRefactor()) { + notifyListenersAboutInteraction(key) + } } - mainExecutor.execute { - notifyListenersAboutInteraction(key) + if (!lifetimeExtensionRefactor()) { + mainExecutor.execute { + notifyListenersAboutInteraction(key) + } } } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 7455fe0043f8..fc7b87317344 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1355,7 +1355,8 @@ public class NotificationManagerService extends SystemService { nv.recycle(); reportUserInteraction(r); mAssistants.notifyAssistantActionClicked(r, action, generatedByAssistant); - // Notifications that have been interacted with don't need to be lifetime extended. + // Notifications that have been interacted with should no longer be lifetime + // extended. if (lifetimeExtensionRefactor()) { r.getSbn().getNotification().flags &= ~FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; } @@ -1524,9 +1525,32 @@ public class NotificationManagerService extends SystemService { @Override public void onNotificationDirectReplied(String key) { exitIdle(); + String packageName = null; + final int packageImportance; synchronized (mNotificationLock) { NotificationRecord r = mNotificationsByKey.get(key); if (r != null) { + packageName = r.getSbn().getPackageName(); + } + } + if (lifetimeExtensionRefactor() && packageName != null) { + packageImportance = getPackageImportanceWithIdentity(packageName); + } else { + packageImportance = IMPORTANCE_NONE; + } + synchronized (mNotificationLock) { + NotificationRecord r = mNotificationsByKey.get(key); + if (r != null) { + // If the notification is already marked as lifetime extended before we record + // the new direct reply, there must have been a previous lifetime extension + // event, and the app has already cancelled the notification, or does not + // respond to direct replies with updates. So we need to update System UI + // immediately. + if (lifetimeExtensionRefactor()) { + maybeNotifySystemUiListenerLifetimeExtendedLocked(r, + r.getSbn().getPackageName(), packageImportance); + } + r.recordDirectReplied(); mMetricsLogger.write(r.getLogMaker() .setCategory(MetricsEvent.NOTIFICATION_DIRECT_REPLY_ACTION) @@ -1557,10 +1581,31 @@ public class NotificationManagerService extends SystemService { @Override public void onNotificationSmartReplySent(String key, int replyIndex, CharSequence reply, int notificationLocation, boolean modifiedBeforeSending) { - + String packageName = null; + final int packageImportance; synchronized (mNotificationLock) { NotificationRecord r = mNotificationsByKey.get(key); if (r != null) { + packageName = r.getSbn().getPackageName(); + } + } + if (lifetimeExtensionRefactor() && packageName != null) { + packageImportance = getPackageImportanceWithIdentity(packageName); + } else { + packageImportance = IMPORTANCE_NONE; + } + synchronized (mNotificationLock) { + NotificationRecord r = mNotificationsByKey.get(key); + if (r != null) { + // If the notification is already marked as lifetime extended before we record + // the new direct reply, there must have been a previous lifetime extension + // event, and the app has already cancelled the notification, or does not + // respond to direct replies with updates. So we need to update System UI + // immediately. + if (lifetimeExtensionRefactor()) { + maybeNotifySystemUiListenerLifetimeExtendedLocked(r, + r.getSbn().getPackageName(), packageImportance); + } r.recordSmartReplied(); LogMaker logMaker = r.getLogMaker() .setCategory(MetricsEvent.SMART_REPLY_ACTION) @@ -7735,7 +7780,7 @@ public class NotificationManagerService extends SystemService { notification.flags &= ~FLAG_FSI_REQUESTED_BUT_DENIED; - // Apps should not create notifications that are lifetime extended. + // Apps cannot post notifications that are lifetime extended. if (lifetimeExtensionRefactor()) { notification.flags &= ~FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; } @@ -12005,8 +12050,10 @@ public class NotificationManagerService extends SystemService { @Override public void onServiceAdded(ManagedServiceInfo info) { if (lifetimeExtensionRefactor()) { - // Only System or System UI can call registerSystemService, so if the caller is not - // system, we know it's system UI. + // Generally, only System or System UI should have the permissions to call + // registerSystemService. + // isCallerSystemorPhone tells us whether the caller is System. Then, if it's not + // the system, we know it's system UI. info.isSystemUi = !isCallerSystemOrPhone(); } final INotificationListener listener = (INotificationListener) info.service; diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 92dad2598538..cff7f460feb5 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -5842,6 +5842,30 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testStats_DirectReplyLifetimeExtendedPostsUpdate() throws Exception { + mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR); + final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); + r.getSbn().getNotification().flags |= FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; + mService.addNotification(r); + + mService.mNotificationDelegate.onNotificationDirectReplied(r.getKey()); + waitForIdle(); + + assertThat(mService.getNotificationRecord(r.getKey()).getStats().hasDirectReplied()) + .isTrue(); + // Checks that a post update is sent. + verify(mWorkerHandler, times(1)) + .post(any(NotificationManagerService.PostNotificationRunnable.class)); + ArgumentCaptor<NotificationRecord> captor = + ArgumentCaptor.forClass(NotificationRecord.class); + verify(mListeners, times(1)).prepareNotifyPostedLocked(captor.capture(), any(), + anyBoolean()); + assertThat(captor.getValue().getNotification().flags + & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY).isEqualTo( + FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY); + } + + @Test public void testStats_updatedOnUserExpansion() throws Exception { NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); mService.addNotification(r); @@ -8507,6 +8531,36 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testStats_SmartReplyAlreadyLifetimeExtendedPostsUpdate() throws Exception { + mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR); + final int replyIndex = 2; + final String reply = "Hello"; + final boolean modifiedBeforeSending = true; + final boolean generatedByAssistant = true; + + NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); + r.getSbn().getNotification().flags |= FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; + r.setSuggestionsGeneratedByAssistant(generatedByAssistant); + mService.addNotification(r); + + mService.mNotificationDelegate.onNotificationSmartReplySent( + r.getKey(), replyIndex, reply, NOTIFICATION_LOCATION_UNKNOWN, + modifiedBeforeSending); + waitForIdle(); + + // Checks that a post update is sent. + verify(mWorkerHandler, times(1)) + .post(any(NotificationManagerService.PostNotificationRunnable.class)); + ArgumentCaptor<NotificationRecord> captor = + ArgumentCaptor.forClass(NotificationRecord.class); + verify(mListeners, times(1)).prepareNotifyPostedLocked(captor.capture(), any(), + anyBoolean()); + assertThat(captor.getValue().getNotification().flags + & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY).isEqualTo( + FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY); + } + + @Test public void testOnNotificationActionClick() { final int actionIndex = 2; final Notification.Action action = @@ -8537,6 +8591,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { final Notification.Action action = new Notification.Action.Builder(null, "text", PendingIntent.getActivity( mContext, 0, new Intent(), PendingIntent.FLAG_IMMUTABLE)).build(); + final boolean generatedByAssistant = false; + // Creates a notification marked as being lifetime extended. NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); r.getSbn().getNotification().flags |= FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY; @@ -8550,6 +8606,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // The flag is removed, so the notification is no longer lifetime extended. assertThat(r.getSbn().getNotification().flags & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY).isEqualTo(0); + + // The record is sent out without the flag. + ArgumentCaptor<NotificationRecord> captor = + ArgumentCaptor.forClass(NotificationRecord.class); + verify(mAssistants, times(1)).notifyAssistantActionClicked( + captor.capture(), eq(action), eq(generatedByAssistant)); + assertThat(captor.getValue().getNotification().flags + & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY).isEqualTo(0); } @Test |