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

Commit f75019b8 authored by Selim Cinek's avatar Selim Cinek Committed by Android (Google) Code Review
Browse files

Merge "Keep notification when sending smart reply." into pi-dev

parents f9491caf 8cc15d2e
Loading
Loading
Loading
Loading
+20 −0
Original line number Original line Diff line number Diff line
@@ -983,6 +983,17 @@ public class Notification implements Parcelable
     */
     */
    public static final String EXTRA_SHOW_REMOTE_INPUT_SPINNER = "android.remoteInputSpinner";
    public static final String EXTRA_SHOW_REMOTE_INPUT_SPINNER = "android.remoteInputSpinner";


    /**
     * {@link #extras} key: boolean as supplied to
     * {@link Builder#setHideSmartReplies(boolean)}.
     *
     * If set to true, then any smart reply buttons will be hidden.
     *
     * @see Builder#setHideSmartReplies(boolean)
     * @hide
     */
    public static final String EXTRA_HIDE_SMART_REPLIES = "android.hideSmartReplies";

    /**
    /**
     * {@link #extras} key: this is a small piece of additional text as supplied to
     * {@link #extras} key: this is a small piece of additional text as supplied to
     * {@link Builder#setContentInfo(CharSequence)}.
     * {@link Builder#setContentInfo(CharSequence)}.
@@ -3594,6 +3605,15 @@ public class Notification implements Parcelable
            return this;
            return this;
        }
        }


        /**
         * Sets whether smart reply buttons should be hidden.
         * @hide
         */
        public Builder setHideSmartReplies(boolean hideSmartReplies) {
            mN.extras.putBoolean(EXTRA_HIDE_SMART_REPLIES, hideSmartReplies);
            return this;
        }

        /**
        /**
         * Sets the number of items this notification represents. May be displayed as a badge count
         * Sets the number of items this notification represents. May be displayed as a badge count
         * for Launchers that support badging.
         * for Launchers that support badging.
+7 −0
Original line number Original line Diff line number Diff line
@@ -1384,6 +1384,13 @@ public class NotificationContentView extends FrameLayout {
            smartReplyContainer.setVisibility(View.GONE);
            smartReplyContainer.setVisibility(View.GONE);
            return null;
            return null;
        }
        }
        // If we are keeping the notification around while sending we don't want to add the buttons.
        boolean hideSmartReplies = entry.notification.getNotification()
                .extras.getBoolean(Notification.EXTRA_HIDE_SMART_REPLIES, false);
        if (hideSmartReplies) {
            smartReplyContainer.setVisibility(View.GONE);
            return null;
        }
        SmartReplyView smartReplyView = null;
        SmartReplyView smartReplyView = null;
        if (smartReplyContainer.getChildCount() == 0) {
        if (smartReplyContainer.getChildCount() == 0) {
            smartReplyView = SmartReplyView.inflate(mContext, smartReplyContainer);
            smartReplyView = SmartReplyView.inflate(mContext, smartReplyContainer);
+82 −11
Original line number Original line Diff line number Diff line
@@ -113,6 +113,8 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
            Dependency.get(ForegroundServiceController.class);
            Dependency.get(ForegroundServiceController.class);
    protected final NotificationListener mNotificationListener =
    protected final NotificationListener mNotificationListener =
            Dependency.get(NotificationListener.class);
            Dependency.get(NotificationListener.class);
    private final SmartReplyController mSmartReplyController =
            Dependency.get(SmartReplyController.class);


    protected IStatusBarService mBarService;
    protected IStatusBarService mBarService;
    protected NotificationPresenter mPresenter;
    protected NotificationPresenter mPresenter;
@@ -127,6 +129,13 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
    protected boolean mDisableNotificationAlerts;
    protected boolean mDisableNotificationAlerts;
    protected NotificationListContainer mListContainer;
    protected NotificationListContainer mListContainer;
    private ExpandableNotificationRow.OnAppOpsClickListener mOnAppOpsClickListener;
    private ExpandableNotificationRow.OnAppOpsClickListener mOnAppOpsClickListener;
    /**
     * Notifications with keys in this set are not actually around anymore. We kept them around
     * when they were canceled in response to a remote input interaction. This allows us to show
     * what you replied and allows you to continue typing into it.
     */
    private final ArraySet<String> mKeysKeptForRemoteInput = new ArraySet<>();



    private final class NotificationClicker implements View.OnClickListener {
    private final class NotificationClicker implements View.OnClickListener {


@@ -220,6 +229,8 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
        }
        }
        pw.print("  mUseHeadsUp=");
        pw.print("  mUseHeadsUp=");
        pw.println(mUseHeadsUp);
        pw.println(mUseHeadsUp);
        pw.print("  mKeysKeptForRemoteInput: ");
        pw.println(mKeysKeptForRemoteInput);
    }
    }


    public NotificationEntryManager(Context context) {
    public NotificationEntryManager(Context context) {
@@ -374,6 +385,12 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
        final NotificationVisibility nv = NotificationVisibility.obtain(n.getKey(), rank, count,
        final NotificationVisibility nv = NotificationVisibility.obtain(n.getKey(), rank, count,
                true);
                true);
        NotificationData.Entry entry = mNotificationData.get(n.getKey());
        NotificationData.Entry entry = mNotificationData.get(n.getKey());

        if (FORCE_REMOTE_INPUT_HISTORY
                && mKeysKeptForRemoteInput.contains(n.getKey())) {
            mKeysKeptForRemoteInput.remove(n.getKey());
        }

        mRemoteInputManager.onPerformRemoveNotification(n, entry);
        mRemoteInputManager.onPerformRemoveNotification(n, entry);
        final String pkg = n.getPackageName();
        final String pkg = n.getPackageName();
        final String tag = n.getTag();
        final String tag = n.getTag();
@@ -491,10 +508,35 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
            }
            }
            if (updated) {
            if (updated) {
                Log.w(TAG, "Keeping notification around after sending remote input "+ entry.key);
                Log.w(TAG, "Keeping notification around after sending remote input "+ entry.key);
                mRemoteInputManager.getKeysKeptForRemoteInput().add(entry.key);
                addKeyKeptForRemoteInput(entry.key);
                return;
                return;
            }
            }
        }
        }

        if (FORCE_REMOTE_INPUT_HISTORY
                && shouldKeepForSmartReply(entry)
                && entry.row != null && !entry.row.isDismissed()) {
            // Turn off the spinner and hide buttons when an app cancels the notification.
            StatusBarNotification newSbn = rebuildNotificationForCanceledSmartReplies(entry);
            boolean updated = false;
            try {
                updateNotificationInternal(newSbn, null);
                updated = true;
            } catch (InflationException e) {
                // Ignore just don't keep the notification around.
            }
            // Treat the reply as longer sending.
            mSmartReplyController.stopSending(entry);
            if (updated) {
                Log.w(TAG, "Keeping notification around after sending smart reply " + entry.key);
                addKeyKeptForRemoteInput(entry.key);
                return;
            }
        }

        // Actually removing notification so smart reply controller can forget about it.
        mSmartReplyController.stopSending(entry);

        if (deferRemoval) {
        if (deferRemoval) {
            mLatestRankingMap = ranking;
            mLatestRankingMap = ranking;
            mHeadsUpEntriesToRemoveOnSwitch.add(mHeadsUpManager.getEntry(key));
            mHeadsUpEntriesToRemoveOnSwitch.add(mHeadsUpManager.getEntry(key));
@@ -536,6 +578,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.


        Notification.Builder b = Notification.Builder
        Notification.Builder b = Notification.Builder
                .recoverBuilder(mContext, sbn.getNotification().clone());
                .recoverBuilder(mContext, sbn.getNotification().clone());
        if (remoteInputText != null) {
            CharSequence[] oldHistory = sbn.getNotification().extras
            CharSequence[] oldHistory = sbn.getNotification().extras
                    .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
                    .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY);
            CharSequence[] newHistory;
            CharSequence[] newHistory;
@@ -547,7 +590,9 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
            }
            }
            newHistory[0] = String.valueOf(remoteInputText);
            newHistory[0] = String.valueOf(remoteInputText);
            b.setRemoteInputHistory(newHistory);
            b.setRemoteInputHistory(newHistory);
        }
        b.setShowRemoteInputSpinner(showSpinner);
        b.setShowRemoteInputSpinner(showSpinner);
        b.setHideSmartReplies(true);


        Notification newNotification = b.build();
        Notification newNotification = b.build();


@@ -563,6 +608,17 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
        return newSbn;
        return newSbn;
    }
    }


    @VisibleForTesting
    StatusBarNotification rebuildNotificationForCanceledSmartReplies(
            NotificationData.Entry entry) {
        return rebuildNotificationWithRemoteInput(entry, null /* remoteInputTest */,
                false /* showSpinner */);
    }

    private boolean shouldKeepForSmartReply(NotificationData.Entry entry) {
        return entry != null && mSmartReplyController.isSendingSmartReply(entry.key);
    }

    private boolean shouldKeepForRemoteInput(NotificationData.Entry entry) {
    private boolean shouldKeepForRemoteInput(NotificationData.Entry entry) {
        if (entry == null) {
        if (entry == null) {
            return false;
            return false;
@@ -792,6 +848,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
        }
        }
        mHeadsUpEntriesToRemoveOnSwitch.remove(entry);
        mHeadsUpEntriesToRemoveOnSwitch.remove(entry);
        mRemoteInputManager.onUpdateNotification(entry);
        mRemoteInputManager.onUpdateNotification(entry);
        mSmartReplyController.stopSending(entry);


        if (key.equals(mGutsManager.getKeyToRemoveOnGutsClosed())) {
        if (key.equals(mGutsManager.getKeyToRemoveOnGutsClosed())) {
            mGutsManager.setKeyToRemoveOnGutsClosed(null);
            mGutsManager.setKeyToRemoveOnGutsClosed(null);
@@ -955,6 +1012,20 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
        return mHeadsUpManager.isHeadsUp(key);
        return mHeadsUpManager.isHeadsUp(key);
    }
    }


    public boolean isNotificationKeptForRemoteInput(String key) {
        return mKeysKeptForRemoteInput.contains(key);
    }

    public void removeKeyKeptForRemoteInput(String key) {
        mKeysKeptForRemoteInput.remove(key);
    }

    public void addKeyKeptForRemoteInput(String key) {
        if (FORCE_REMOTE_INPUT_HISTORY) {
            mKeysKeptForRemoteInput.add(key);
        }
    }

    /**
    /**
     * Callback for NotificationEntryManager.
     * Callback for NotificationEntryManager.
     */
     */
+1 −1
Original line number Original line Diff line number Diff line
@@ -75,7 +75,7 @@ public class NotificationListener extends NotificationListenerWithPlugins {
            mPresenter.getHandler().post(() -> {
            mPresenter.getHandler().post(() -> {
                processForRemoteInput(sbn.getNotification(), mContext);
                processForRemoteInput(sbn.getNotification(), mContext);
                String key = sbn.getKey();
                String key = sbn.getKey();
                mRemoteInputManager.getKeysKeptForRemoteInput().remove(key);
                mEntryManager.removeKeyKeptForRemoteInput(key);
                boolean isUpdate =
                boolean isUpdate =
                        mEntryManager.getNotificationData().get(key) != null;
                        mEntryManager.getNotificationData().get(key) != null;
                // In case we don't allow child notifications, we ignore children of
                // In case we don't allow child notifications, we ignore children of
+2 −17
Original line number Original line Diff line number Diff line
@@ -77,12 +77,6 @@ public class NotificationRemoteInputManager implements Dumpable {
    protected final NotificationLockscreenUserManager mLockscreenUserManager =
    protected final NotificationLockscreenUserManager mLockscreenUserManager =
            Dependency.get(NotificationLockscreenUserManager.class);
            Dependency.get(NotificationLockscreenUserManager.class);


    /**
     * Notifications with keys in this set are not actually around anymore. We kept them around
     * when they were canceled in response to a remote input interaction. This allows us to show
     * what you replied and allows you to continue typing into it.
     */
    protected final ArraySet<String> mKeysKeptForRemoteInput = new ArraySet<>();
    protected final Context mContext;
    protected final Context mContext;
    private final UserManager mUserManager;
    private final UserManager mUserManager;


@@ -290,7 +284,8 @@ public class NotificationRemoteInputManager implements Dumpable {
        mRemoteInputController.addCallback(new RemoteInputController.Callback() {
        mRemoteInputController.addCallback(new RemoteInputController.Callback() {
            @Override
            @Override
            public void onRemoteInputSent(NotificationData.Entry entry) {
            public void onRemoteInputSent(NotificationData.Entry entry) {
                if (FORCE_REMOTE_INPUT_HISTORY && mKeysKeptForRemoteInput.contains(entry.key)) {
                if (FORCE_REMOTE_INPUT_HISTORY
                        && mEntryManager.isNotificationKeptForRemoteInput(entry.key)) {
                    mEntryManager.removeNotification(entry.key, null);
                    mEntryManager.removeNotification(entry.key, null);
                } else if (mRemoteInputEntriesToRemoveOnCollapse.contains(entry)) {
                } else if (mRemoteInputEntriesToRemoveOnCollapse.contains(entry)) {
                    // We're currently holding onto this notification, but from the apps point of
                    // We're currently holding onto this notification, but from the apps point of
@@ -340,10 +335,6 @@ public class NotificationRemoteInputManager implements Dumpable {
        if (mRemoteInputController.isRemoteInputActive(entry)) {
        if (mRemoteInputController.isRemoteInputActive(entry)) {
            mRemoteInputController.removeRemoteInput(entry, null);
            mRemoteInputController.removeRemoteInput(entry, null);
        }
        }
        if (FORCE_REMOTE_INPUT_HISTORY
                && mKeysKeptForRemoteInput.contains(n.getKey())) {
            mKeysKeptForRemoteInput.remove(n.getKey());
        }
    }
    }


    public void removeRemoteInputEntriesKeptUntilCollapsed() {
    public void removeRemoteInputEntriesKeptUntilCollapsed() {
@@ -368,8 +359,6 @@ public class NotificationRemoteInputManager implements Dumpable {
        pw.println("NotificationRemoteInputManager state:");
        pw.println("NotificationRemoteInputManager state:");
        pw.print("  mRemoteInputEntriesToRemoveOnCollapse: ");
        pw.print("  mRemoteInputEntriesToRemoveOnCollapse: ");
        pw.println(mRemoteInputEntriesToRemoveOnCollapse);
        pw.println(mRemoteInputEntriesToRemoveOnCollapse);
        pw.print("  mKeysKeptForRemoteInput: ");
        pw.println(mKeysKeptForRemoteInput);
    }
    }


    public void bindRow(ExpandableNotificationRow row) {
    public void bindRow(ExpandableNotificationRow row) {
@@ -377,10 +366,6 @@ public class NotificationRemoteInputManager implements Dumpable {
        row.setRemoteViewClickHandler(mOnClickHandler);
        row.setRemoteViewClickHandler(mOnClickHandler);
    }
    }


    public Set<String> getKeysKeptForRemoteInput() {
        return mKeysKeptForRemoteInput;
    }

    @VisibleForTesting
    @VisibleForTesting
    public Set<NotificationData.Entry> getRemoteInputEntriesToRemoveOnCollapse() {
    public Set<NotificationData.Entry> getRemoteInputEntriesToRemoveOnCollapse() {
        return mRemoteInputEntriesToRemoveOnCollapse;
        return mRemoteInputEntriesToRemoveOnCollapse;
Loading