Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8a52dc3a authored by Gustav Sennton's avatar Gustav Sennton
Browse files

Block clicks on smart actions and replies just after creation/update.

To avoid accidental clicks on smart actions and replies we here block
clicks on those buttons just after they are created. We block clicks
on those buttons when a notification is updated - but only if the
buttons are new, or different from previous buttons shown in the
notification. I.e. if the notification is updated but the smart
suggestion buttons stay the same we don't block clicks on them.

Bug: 128683184
Test: manually ensure clicks are blocked within the initialization
delay (for new / changed buttons), and ensure the delay changes
when calling
adb shell device_config put systemui ssin_onclick_init_delay X
where X is the delay in ms.
Test: SmartReplyConstantsTest, SmartReplyViewTest
Change-Id: I9a44eb6ade6579a42e35b36cce4bd5863332c60e
parent 2a4e6f6e
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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}.
+4 −0
Original line number Diff line number Diff line
@@ -469,6 +469,10 @@
         -->
    <integer name="config_smart_replies_in_notifications_max_num_actions">-1</integer>

    <!-- Smart replies in notifications: Delay (ms) before smart suggestions are clickable, since
         they were added. -->
    <integer name="config_smart_replies_in_notifications_onclick_init_delay">200</integer>

    <!-- Screenshot editing default activity.  Must handle ACTION_EDIT image/png intents.
         Blank sends the user to the Chooser first.
         This name is in the ComponentName flattened format (package/class)  -->
+8 −0
Original line number Diff line number Diff line
@@ -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;
+8 −5
Original line number Diff line number Diff line
@@ -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;

@@ -284,7 +285,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,
@@ -346,20 +348,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;
    }
@@ -907,7 +909,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;
+14 −6
Original line number Diff line number Diff line
@@ -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();
Loading