diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java index 495a5fbb66657..6d0a8646b3a77 100644 --- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java @@ -81,6 +81,12 @@ public final class SystemUiDeviceConfigFlags { */ public static final String SSIN_MAX_NUM_ACTIONS = "ssin_max_num_actions"; + /** + * (int) The amount of time (ms) before smart suggestions are clickable, since the suggestions + * were added. + */ + public static final String SSIN_ONCLICK_INIT_DELAY = "ssin_onclick_init_delay"; + /** * The default component of * {@link android.service.notification.NotificationAssistantService}. diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index d6906f3988cda..73386879a20d7 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -469,6 +469,10 @@ --> -1 + + 200 + 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 efdcd053bc54c..6b2efaab0a644 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 @@ -100,6 +100,7 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.HeadsUpManager; +import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -3194,6 +3195,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mAmbientGoingAway = goingAway; } + /** + * Returns the Smart Suggestions backing the smart suggestion buttons in the notification. + */ + public SmartRepliesAndActions getExistingSmartRepliesAndActions() { + return mPrivateLayout.getCurrentSmartRepliesAndActions(); + } + @VisibleForTesting protected void setChildrenContainer(NotificationChildrenContainer childrenContainer) { mChildrenContainer = childrenContainer; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java index 18dcf4c55d21e..396cd73f9a225 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java @@ -44,6 +44,7 @@ import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewW import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.InflatedSmartReplies; +import com.android.systemui.statusbar.policy.InflatedSmartReplies.SmartRepliesAndActions; import com.android.systemui.statusbar.policy.SmartReplyConstants; import com.android.systemui.util.Assert; @@ -282,7 +283,8 @@ public class NotificationContentInflater { mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient, packageContext); result = inflateSmartReplyViews(result, reInflateFlags, mRow.getEntry(), - mRow.getContext(), mRow.getHeadsUpManager()); + mRow.getContext(), mRow.getHeadsUpManager(), + mRow.getExistingSmartRepliesAndActions()); apply( inflateSynchronously, result, @@ -344,20 +346,20 @@ public class NotificationContentInflater { private static InflationProgress inflateSmartReplyViews(InflationProgress result, @InflationFlag int reInflateFlags, NotificationEntry entry, Context context, - HeadsUpManager headsUpManager) { + HeadsUpManager headsUpManager, SmartRepliesAndActions previousSmartRepliesAndActions) { SmartReplyConstants smartReplyConstants = Dependency.get(SmartReplyConstants.class); SmartReplyController smartReplyController = Dependency.get(SmartReplyController.class); if ((reInflateFlags & FLAG_CONTENT_VIEW_EXPANDED) != 0 && result.newExpandedView != null) { result.expandedInflatedSmartReplies = InflatedSmartReplies.inflate( context, entry, smartReplyConstants, smartReplyController, - headsUpManager); + headsUpManager, previousSmartRepliesAndActions); } if ((reInflateFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0 && result.newHeadsUpView != null) { result.headsUpInflatedSmartReplies = InflatedSmartReplies.inflate( context, entry, smartReplyConstants, smartReplyController, - headsUpManager); + headsUpManager, previousSmartRepliesAndActions); } return result; } @@ -905,7 +907,8 @@ public class NotificationContentInflater { mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient, packageContext); return inflateSmartReplyViews(inflationProgress, mReInflateFlags, mRow.getEntry(), - mRow.getContext(), mRow.getHeadsUpManager()); + mRow.getContext(), mRow.getHeadsUpManager(), + mRow.getExistingSmartRepliesAndActions()); } catch (Exception e) { mError = e; return null; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index 78500357f41f3..b81d81438ea39 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -93,6 +93,7 @@ public class NotificationContentView extends FrameLayout { private SmartReplyController mSmartReplyController; private InflatedSmartReplies mExpandedInflatedSmartReplies; private InflatedSmartReplies mHeadsUpInflatedSmartReplies; + private SmartRepliesAndActions mCurrentSmartRepliesAndActions; private NotificationViewWrapper mContractedWrapper; private NotificationViewWrapper mExpandedWrapper; @@ -1259,18 +1260,18 @@ public class NotificationContentView extends FrameLayout { // the same SmartRepliesAndActions to avoid discrepancies between the two views. We here // reuse that object for our local SmartRepliesAndActions to avoid discrepancies between // this class and the InflatedSmartReplies classes. - SmartRepliesAndActions smartRepliesAndActions = mExpandedInflatedSmartReplies != null + mCurrentSmartRepliesAndActions = mExpandedInflatedSmartReplies != null ? mExpandedInflatedSmartReplies.getSmartRepliesAndActions() : mHeadsUpInflatedSmartReplies.getSmartRepliesAndActions(); if (DEBUG) { Log.d(TAG, String.format("Adding suggestions for %s, %d actions, and %d replies.", entry.notification.getKey(), - smartRepliesAndActions.smartActions == null ? 0 : - smartRepliesAndActions.smartActions.actions.size(), - smartRepliesAndActions.smartReplies == null ? 0 : - smartRepliesAndActions.smartReplies.choices.length)); + mCurrentSmartRepliesAndActions.smartActions == null ? 0 : + mCurrentSmartRepliesAndActions.smartActions.actions.size(), + mCurrentSmartRepliesAndActions.smartReplies == null ? 0 : + mCurrentSmartRepliesAndActions.smartReplies.choices.length)); } - applySmartReplyView(smartRepliesAndActions, entry); + applySmartReplyView(mCurrentSmartRepliesAndActions, entry); } private void applyRemoteInput(NotificationEntry entry, boolean hasFreeformRemoteInput) { @@ -1472,6 +1473,13 @@ public class NotificationContentView extends FrameLayout { } } + /** + * Returns the smart replies and actions currently shown in the notification. + */ + @Nullable public SmartRepliesAndActions getCurrentSmartRepliesAndActions() { + return mCurrentSmartRepliesAndActions; + } + public void closeRemoteInput() { if (mHeadsUpRemoteInput != null) { mHeadsUpRemoteInput.close(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java index 5b2e398b66e14..ee78a723a49c6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java @@ -28,15 +28,19 @@ import android.util.Log; import android.util.Pair; import android.widget.Button; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.systemui.Dependency; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.DevicePolicyManagerWrapper; import com.android.systemui.shared.system.PackageManagerWrapper; +import com.android.systemui.statusbar.NotificationUiAdjustment; import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; /** @@ -79,29 +83,52 @@ public class InflatedSmartReplies { NotificationEntry entry, SmartReplyConstants smartReplyConstants, SmartReplyController smartReplyController, - HeadsUpManager headsUpManager) { - SmartRepliesAndActions smartRepliesAndActions = + HeadsUpManager headsUpManager, + SmartRepliesAndActions existingSmartRepliesAndActions) { + SmartRepliesAndActions newSmartRepliesAndActions = chooseSmartRepliesAndActions(smartReplyConstants, entry); - if (!shouldShowSmartReplyView(entry, smartRepliesAndActions)) { + if (!shouldShowSmartReplyView(entry, newSmartRepliesAndActions)) { return new InflatedSmartReplies(null /* smartReplyView */, - null /* smartSuggestionButtons */, smartRepliesAndActions); + null /* smartSuggestionButtons */, newSmartRepliesAndActions); } + // Only block clicks if the smart buttons are different from the previous set - to avoid + // scenarios where a user incorrectly cannot click smart buttons because the notification is + // updated. + boolean delayOnClickListener = + !areSuggestionsSimilar(existingSmartRepliesAndActions, newSmartRepliesAndActions); + SmartReplyView smartReplyView = SmartReplyView.inflate(context); List