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

Commit 1a101dbc authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix remote input view clobbering" into nyc-dev

parents fab88eab 4c1fcc89
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -3351,7 +3351,8 @@ public class Notification implements Parcelable
        }

        private void resetStandardTemplateWithActions(RemoteViews big) {
            big.setViewVisibility(R.id.actions_container, View.GONE);
            // actions_container is only reset when there are no actions to avoid focus issues with
            // remote inputs.
            big.setViewVisibility(R.id.actions, View.GONE);
            big.removeAllViews(R.id.actions);

@@ -3396,6 +3397,8 @@ public class Notification implements Parcelable
                    }
                    big.addView(R.id.actions, button);
                }
            } else {
                big.setViewVisibility(R.id.actions_container, View.GONE);
            }

            CharSequence[] replyText = mN.extras.getCharSequenceArray(EXTRA_REMOTE_INPUT_HISTORY);
+55 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.Context;
import android.graphics.Rect;
@@ -118,6 +119,8 @@ public class NotificationContentView extends FrameLayout {
    private int mTransformationStartVisibleType;
    private boolean mUserExpanding;
    private int mSingleLineWidthIndention;
    private PendingIntent mPreviousExpandedRemoteInputIntent;
    private PendingIntent mPreviousHeadsUpRemoteInputIntent;

    public NotificationContentView(Context context, AttributeSet attrs) {
        super(context, attrs);
@@ -280,13 +283,19 @@ public class NotificationContentView extends FrameLayout {
            mContractedChild.animate().cancel();
            removeView(mContractedChild);
        }
        mPreviousExpandedRemoteInputIntent =
                mExpandedRemoteInput != null ? mExpandedRemoteInput.getPendingIntent() : null;
        if (mExpandedChild != null) {
            mExpandedChild.animate().cancel();
            removeView(mExpandedChild);
            mExpandedRemoteInput = null;
        }
        mPreviousHeadsUpRemoteInputIntent =
                mHeadsUpRemoteInput != null ? mHeadsUpRemoteInput.getPendingIntent() : null;
        if (mHeadsUpChild != null) {
            mHeadsUpChild.animate().cancel();
            removeView(mHeadsUpChild);
            mHeadsUpRemoteInput = null;
        }
        mContractedChild = null;
        mExpandedChild = null;
@@ -496,6 +505,12 @@ public class NotificationContentView extends FrameLayout {
        }
        int visibleType = calculateVisibleType();
        if (visibleType != mVisibleType || force) {
            View visibleView = getViewForVisibleType(visibleType);
            if (visibleView != null) {
                visibleView.setVisibility(VISIBLE);
                transferRemoteInputFocus(visibleType);
            }

            if (animate && ((visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null)
                    || (visibleType == VISIBLE_TYPE_HEADSUP && mHeadsUpChild != null)
                    || (visibleType == VISIBLE_TYPE_SINGLELINE && mSingleLineView != null)
@@ -559,6 +574,19 @@ public class NotificationContentView extends FrameLayout {
        });
    }

    private void transferRemoteInputFocus(int visibleType) {
        if (visibleType == VISIBLE_TYPE_HEADSUP
                && mHeadsUpRemoteInput != null
                && (mExpandedRemoteInput != null && mExpandedRemoteInput.isActive())) {
            mHeadsUpRemoteInput.stealFocusFrom(mExpandedRemoteInput);
        }
        if (visibleType == VISIBLE_TYPE_EXPANDED
                && mExpandedRemoteInput != null
                && (mHeadsUpRemoteInput != null && mHeadsUpRemoteInput.isActive())) {
            mExpandedRemoteInput.stealFocusFrom(mHeadsUpRemoteInput);
        }
    }

    /**
     * @param visibleType one of the static enum types in this view
     * @return the corresponding transformable view according to the given visible type
@@ -736,6 +764,8 @@ public class NotificationContentView extends FrameLayout {
        updateShowingLegacyBackground();
        selectLayout(false /* animate */, true /* force */);
        setDark(mDark, false /* animate */, 0 /* delay */);
        mPreviousExpandedRemoteInputIntent = null;
        mPreviousHeadsUpRemoteInputIntent = null;
    }

    private void updateSingleLineView() {
@@ -771,19 +801,23 @@ public class NotificationContentView extends FrameLayout {

        View bigContentView = mExpandedChild;
        if (bigContentView != null) {
            mExpandedRemoteInput = applyRemoteInput(bigContentView, entry, hasRemoteInput);
            mExpandedRemoteInput = applyRemoteInput(bigContentView, entry, hasRemoteInput,
                    mPreviousExpandedRemoteInputIntent);
        } else {
            mExpandedRemoteInput = null;
        }

        View headsUpContentView = mHeadsUpChild;
        if (headsUpContentView != null) {
            mHeadsUpRemoteInput = applyRemoteInput(headsUpContentView, entry, hasRemoteInput);
            mHeadsUpRemoteInput = applyRemoteInput(headsUpContentView, entry, hasRemoteInput,
                    mPreviousHeadsUpRemoteInputIntent);
        } else {
            mHeadsUpRemoteInput = null;
        }
    }

    private RemoteInputView applyRemoteInput(View view, NotificationData.Entry entry, boolean hasRemoteInput) {
    private RemoteInputView applyRemoteInput(View view, NotificationData.Entry entry,
            boolean hasRemoteInput, PendingIntent existingPendingIntent) {
        View actionContainerCandidate = view.findViewById(
                com.android.internal.R.id.actions_container);
        if (actionContainerCandidate instanceof FrameLayout) {
@@ -814,6 +848,24 @@ public class NotificationContentView extends FrameLayout {
                existing.setBackgroundColor(NotificationColorUtil.ensureTextBackgroundColor(color,
                        mContext.getColor(R.color.remote_input_text),
                        mContext.getColor(R.color.remote_input_hint)));

                if (existingPendingIntent != null || existing.isActive()) {
                    // The current action could be gone, or the pending intent no longer valid.
                    // If we find a matching action in the new notification, focus, otherwise close.
                    Notification.Action[] actions = entry.notification.getNotification().actions;
                    if (existingPendingIntent != null) {
                        existing.setPendingIntent(existingPendingIntent);
                    }
                    if (existing.updatePendingIntentFromActions(actions)) {
                        if (!existing.isActive()) {
                            existing.focus();
                        }
                    } else {
                        if (existing.isActive()) {
                            existing.close();
                        }
                    }
                }
            }
            return existing;
        }
+59 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.statusbar.policy;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.Context;
@@ -197,6 +198,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
    }

    public void focus() {
        setVisibility(VISIBLE);
        mController.addRemoteInput(mEntry);
        mEditText.setInnerFocusable(true);
        mEditText.mShowImeOnInputConnection = true;
@@ -275,6 +277,63 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
        }
    }

    public boolean isActive() {
        return mEditText.isFocused();
    }

    public void stealFocusFrom(RemoteInputView other) {
        other.close();
        setPendingIntent(other.mPendingIntent);
        setRemoteInput(other.mRemoteInputs, other.mRemoteInput);
        focus();
    }

    /**
     * Tries to find an action in {@param actions} that matches the current pending intent
     * of this view and updates its state to that of the found action
     *
     * @return true if a matching action was found, false otherwise
     */
    public boolean updatePendingIntentFromActions(Notification.Action[] actions) {
        boolean found = false;
        if (mPendingIntent == null || actions == null) {
            return false;
        }
        Intent current = mPendingIntent.getIntent();
        if (current == null) {
            return false;
        }

        for (Notification.Action a : actions) {
            RemoteInput[] inputs = a.getRemoteInputs();
            if (a.actionIntent == null || inputs == null) {
                continue;
            }
            Intent candidate = a.actionIntent.getIntent();
            if (!current.filterEquals(candidate)) {
                continue;
            }

            RemoteInput input = null;
            for (RemoteInput i : inputs) {
                if (i.getAllowFreeFormInput()) {
                    input = i;
                }
            }
            if (input == null) {
                continue;
            }
            setPendingIntent(a.actionIntent);
            setRemoteInput(inputs, input);
            return true;
        }
        return false;
    }

    public PendingIntent getPendingIntent() {
        return mPendingIntent;
    }

    /**
     * An EditText that changes appearance based on whether it's focusable and becomes
     * un-focusable whenever the user navigates away from it or it becomes invisible.