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

Commit 27ecbde0 authored by Steve Elliott's avatar Steve Elliott
Browse files

[RemoteInputView] move data fields to Controller

These fields were used to track some non-View-related data for
RemoteInputs.

Test: manual
Bug: 193539698
Change-Id: I220060d0ab9e77bdba6f8aa9956b27cc0b1183d8
parent 40ca086c
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -507,12 +507,11 @@ public class NotificationRemoteInputManager implements Dumpable {
                Math.max(cx + cy, cx + (h - cy)),
                Math.max((w - cx) + cy, (w - cx) + (h - cy)));

        riv.setRevealParameters(cx, cy, r);
        riv.setPendingIntent(pendingIntent);
        riv.getController().setRevealParams(new RemoteInputView.RevealParams(cx, cy, r));
        riv.getController().setPendingIntent(pendingIntent);
        riv.setRemoteInput(inputs, input, editedSuggestionInfo);
        riv.getController().setRemoteInput(input);
        riv.getController().setRemoteInputs(inputs);
        riv.getController().setEditedSuggestionInfo(editedSuggestionInfo);
        riv.focusAnimated();
        if (userMessageContent != null) {
            riv.setEditTextContent(userMessageContent);
+16 −9
Original line number Diff line number Diff line
@@ -413,7 +413,10 @@ public class NotificationContentView extends FrameLayout implements Notification
            if (mExpandedRemoteInput != null) {
                mExpandedRemoteInput.onNotificationUpdateOrReset();
                if (mExpandedRemoteInput.isActive()) {
                    mPreviousExpandedRemoteInputIntent = mExpandedRemoteInput.getPendingIntent();
                    if (mExpandedRemoteInputController != null) {
                        mPreviousExpandedRemoteInputIntent =
                                mExpandedRemoteInputController.getPendingIntent();
                    }
                    mCachedExpandedRemoteInput = mExpandedRemoteInput;
                    mCachedExpandedRemoteInputViewController = mExpandedRemoteInputController;
                    mExpandedRemoteInput.dispatchStartTemporaryDetach();
@@ -460,7 +463,10 @@ public class NotificationContentView extends FrameLayout implements Notification
            if (mHeadsUpRemoteInput != null) {
                mHeadsUpRemoteInput.onNotificationUpdateOrReset();
                if (mHeadsUpRemoteInput.isActive()) {
                    mPreviousHeadsUpRemoteInputIntent = mHeadsUpRemoteInput.getPendingIntent();
                    if (mHeadsUpRemoteInputController != null) {
                        mPreviousHeadsUpRemoteInputIntent =
                                mHeadsUpRemoteInputController.getPendingIntent();
                    }
                    mCachedHeadsUpRemoteInput = mHeadsUpRemoteInput;
                    mCachedHeadsUpRemoteInputViewController = mHeadsUpRemoteInputController;
                    mHeadsUpRemoteInput.dispatchStartTemporaryDetach();
@@ -961,14 +967,16 @@ public class NotificationContentView extends FrameLayout implements Notification

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

@@ -1313,7 +1321,6 @@ public class NotificationContentView extends FrameLayout implements Notification
                    // If we find a matching action in the new notification, focus, otherwise close.
                    Notification.Action[] actions = entry.getSbn().getNotification().actions;
                    if (existingPendingIntent != null) {
                        result.mView.setPendingIntent(existingPendingIntent);
                        result.mController.setPendingIntent(existingPendingIntent);
                    }
                    if (result.mController.updatePendingIntentFromActions(actions)) {
+31 −58
Original line number Diff line number Diff line
@@ -22,8 +22,6 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.ActivityManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
@@ -75,7 +73,6 @@ import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry.EditedSuggestionInfo;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.LightBarController;
@@ -111,21 +108,15 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
    private ProgressBar mProgressBar;
    private ImageView mDelete;
    private ImageView mDeleteBg;
    // TODO(b/193539698): remove reveal param fields, turn them into parameters where needed
    private int mRevealCx;
    private int mRevealCy;
    private int mRevealR;
    private boolean mColorized;
    private int mTint;
    private boolean mResetting;
    @Nullable private RevealParams mRevealParams;

    // TODO(b/193539698): move these to a Controller
    private RemoteInputController mController;
    private final UiEventLogger mUiEventLogger;
    private NotificationEntry mEntry;
    private PendingIntent mPendingIntent;
    private RemoteInput mRemoteInput;
    private RemoteInput[] mRemoteInputs;
    private boolean mRemoved;
    private NotificationViewWrapper mWrapper;

@@ -397,9 +388,8 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
        // During removal, we get reattached and lose focus. Not hiding in that
        // case to prevent flicker.
        if (!mRemoved) {
            if (animate && mRevealR > 0) {
                Animator reveal = ViewAnimationUtils.createCircularReveal(
                        this, mRevealCx, mRevealCy, mRevealR, 0);
            if (animate && mRevealParams != null && mRevealParams.radius > 0) {
                Animator reveal = mRevealParams.createCircularHideAnimator(this);
                reveal.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
                reveal.setDuration(StackStateAnimator.ANIMATION_DURATION_CLOSE_REMOTE_INPUT);
                reveal.addListener(new AnimatorListenerAdapter() {
@@ -454,30 +444,12 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
        mController.removeSpinning(mEntry.getKey(), mToken);
    }

    public void setPendingIntent(PendingIntent pendingIntent) {
        mPendingIntent = pendingIntent;
    public void setHintText(CharSequence hintText) {
        mEditText.setHint(hintText);
    }

    /**
     * Sets the remote input for this view.
     *
     * @param remoteInputs The remote inputs that need to be sent to the app.
     * @param remoteInput The remote input that needs to be activated.
     * @param editedSuggestionInfo The smart reply that should be inserted in the remote input, or
     *         {@code null} if the user is not editing a smart reply.
     */
    public void setRemoteInput(RemoteInput[] remoteInputs, RemoteInput remoteInput,
            @Nullable EditedSuggestionInfo editedSuggestionInfo) {
        mRemoteInputs = remoteInputs;
        mRemoteInput = remoteInput;
        mEditText.setHint(mRemoteInput.getLabel());
        mEditText.setSupportedMimeTypes(remoteInput.getAllowedDataTypes());

        mEntry.editedSuggestionInfo = editedSuggestionInfo;
        if (editedSuggestionInfo != null) {
            mEntry.remoteInputText = editedSuggestionInfo.originalText;
            mEntry.remoteInputAttachment = null;
        }
    public void setSupportedMimeTypes(Collection<String> mimeTypes) {
        mEditText.setSupportedMimeTypes(mimeTypes);
    }

    /** Populates the text field of the remote input with the given content. */
@@ -486,9 +458,8 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
    }

    public void focusAnimated() {
        if (getVisibility() != VISIBLE) {
            Animator animator = ViewAnimationUtils.createCircularReveal(
                    this, mRevealCx, mRevealCy, 0, mRevealR);
        if (getVisibility() != VISIBLE && mRevealParams != null) {
            Animator animator = mRevealParams.createCircularRevealAnimator(this);
            animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
            animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
            animator.start();
@@ -587,30 +558,12 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
        return mEditText.isFocused() && mEditText.isEnabled();
    }

    // TODO(b/193539698): move this to the controller
    public void stealFocusFrom(RemoteInputView other) {
        other.close();
        setPendingIntent(other.mPendingIntent);
        setRemoteInput(other.mRemoteInputs, other.mRemoteInput, mEntry.editedSuggestionInfo);
        setRevealParameters(other.mRevealCx, other.mRevealCy, other.mRevealR);
        getController().setPendingIntent(other.mPendingIntent);
        getController().setRemoteInput(other.mRemoteInput);
        getController().setRemoteInputs(other.mRemoteInputs);
        focus();
    }

    public PendingIntent getPendingIntent() {
        return mPendingIntent;
    }

    public void setRemoved() {
        mRemoved = true;
    }

    public void setRevealParameters(int cx, int cy, int r) {
        mRevealCx = cx;
        mRevealCy = cy;
        mRevealR = r;
    public void setRevealParameters(@Nullable RevealParams revealParams) {
        mRevealParams = revealParams;
    }

    @Override
@@ -938,4 +891,24 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
        }

    }

    public static class RevealParams {
        final int centerX;
        final int centerY;
        final int radius;

        public RevealParams(int centerX, int centerY, int radius) {
            this.centerX = centerX;
            this.centerY = centerY;
            this.radius = radius;
        }

        Animator createCircularRevealAnimator(View view) {
            return ViewAnimationUtils.createCircularReveal(view, centerX, centerY, radius, 0);
        }

        Animator createCircularHideAnimator(View view) {
            return ViewAnimationUtils.createCircularReveal(view, centerX, centerY, 0, radius);
        }
    }
}
+83 −18
Original line number Diff line number Diff line
@@ -33,7 +33,9 @@ import com.android.systemui.R
import com.android.systemui.statusbar.NotificationRemoteInputManager
import com.android.systemui.statusbar.RemoteInputController
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry.EditedSuggestionInfo
import com.android.systemui.statusbar.policy.RemoteInputView.NotificationRemoteInputEvent
import com.android.systemui.statusbar.policy.RemoteInputView.RevealParams
import com.android.systemui.statusbar.policy.dagger.RemoteInputViewScope
import javax.inject.Inject

@@ -41,6 +43,8 @@ interface RemoteInputViewController {
    fun bind()
    fun unbind()

    val isActive: Boolean

    /**
     * A [NotificationRemoteInputManager.BouncerChecker] that will be used to determine if the
     * device needs to be unlocked before sending the RemoteInput.
@@ -55,6 +59,14 @@ interface RemoteInputViewController {
    /** Other [RemoteInput]s from the notification associated with this Controller. */
    var remoteInputs: Array<RemoteInput>?

    var revealParams: RevealParams?

    /**
     * Sets the smart reply that should be inserted in the remote input, or `null` if the user is
     * not editing a smart reply.
     */
    fun setEditedSuggestionInfo(info: EditedSuggestionInfo?)

    /**
     * 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
@@ -68,6 +80,19 @@ interface RemoteInputViewController {

    /** Unregisters a listener previously registered via [addOnSendRemoteInputListener] */
    fun removeOnSendRemoteInputListener(listener: OnSendRemoteInputListener)

    fun close()

    fun focus()

    fun stealFocusFrom(other: RemoteInputViewController) {
        other.close()
        remoteInput = other.remoteInput
        remoteInputs = other.remoteInputs
        revealParams = other.revealParams
        pendingIntent = other.pendingIntent
        focus()
    }
}

/** Listener for send events  */
@@ -100,15 +125,41 @@ class RemoteInputViewControllerImpl @Inject constructor(

    private var isBound = false

    override var pendingIntent: PendingIntent? = null
    override var bouncerChecker: NotificationRemoteInputManager.BouncerChecker? = null

    override var remoteInput: RemoteInput? = null
        set(value) {
            field = value
            value?.takeIf { isBound }?.let {
                view.setHintText(it.label)
                view.setSupportedMimeTypes(it.allowedDataTypes)
            }
        }

    override var pendingIntent: PendingIntent? = null
    override var remoteInputs: Array<RemoteInput>? = null

    override var revealParams: RevealParams? = null
        set(value) {
            field = value
            if (isBound) {
                view.setRevealParameters(value)
            }
        }

    override val isActive: Boolean get() = view.isActive

    override fun bind() {
        if (isBound) return
        isBound = true

        // TODO: refreshUI method?
        remoteInput?.let {
            view.setHintText(it.label)
            view.setSupportedMimeTypes(it.allowedDataTypes)
        }
        view.setRevealParameters(revealParams)

        view.addOnEditTextFocusChangedListener(onFocusChangeListener)
        view.addOnSendRemoteInputListener(onSendRemoteInputListener)
    }
@@ -121,6 +172,14 @@ class RemoteInputViewControllerImpl @Inject constructor(
        view.removeOnSendRemoteInputListener(onSendRemoteInputListener)
    }

    override fun setEditedSuggestionInfo(info: EditedSuggestionInfo?) {
        entry.editedSuggestionInfo = info
        if (info != null) {
            entry.remoteInputText = info.originalText
            entry.remoteInputAttachment = null
        }
    }

    override fun updatePendingIntentFromActions(actions: Array<Notification.Action>?): Boolean {
        actions ?: return false
        val current: Intent = pendingIntent?.intent ?: return false
@@ -132,8 +191,7 @@ class RemoteInputViewControllerImpl @Inject constructor(
            pendingIntent = actionIntent
            remoteInput = input
            remoteInputs = inputs
            view.pendingIntent = actionIntent
            view.setRemoteInput(inputs, input, null /* editedSuggestionInfo */)
            setEditedSuggestionInfo(null)
            return true
        }
        return false
@@ -148,6 +206,14 @@ class RemoteInputViewControllerImpl @Inject constructor(
        onSendListeners.remove(listener)
    }

    override fun close() {
        view.close()
    }

    override fun focus() {
        view.focus()
    }

    private val onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus ->
        remoteInputQuickSettingsDisabler.setRemoteInputActive(hasFocus)
    }
@@ -217,7 +283,8 @@ class RemoteInputViewControllerImpl @Inject constructor(
     * @return returns intent with granted URI permissions that should be used immediately
     */
    private fun prepareRemoteInput(remoteInput: RemoteInput): Intent =
            if (entry.remoteInputAttachment == null) prepareRemoteInputFromText(remoteInput)
        if (entry.remoteInputAttachment == null)
            prepareRemoteInputFromText(remoteInput)
        else prepareRemoteInputFromData(
                remoteInput,
                entry.remoteInputMimeType,
@@ -232,11 +299,10 @@ class RemoteInputViewControllerImpl @Inject constructor(
        view.clearAttachment()
        entry.remoteInputUri = null
        entry.remoteInputMimeType = null
        if (entry.editedSuggestionInfo == null) {
            RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_FREE_FORM_INPUT)
        } else {
            RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_CHOICE)
        }
        val resultSource = entry.editedSuggestionInfo
                ?.let { RemoteInput.SOURCE_FREE_FORM_INPUT }
                ?: RemoteInput.SOURCE_CHOICE
        RemoteInput.setResultsSource(fillInIntent, resultSource)
        return fillInIntent
    }

@@ -266,11 +332,10 @@ class RemoteInputViewControllerImpl @Inject constructor(
        entry.remoteInputText = fullText

        // mirror prepareRemoteInputFromText for text input
        if (entry.editedSuggestionInfo == null) {
            RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_FREE_FORM_INPUT)
        } else if (entry.remoteInputAttachment == null) {
            RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_CHOICE)
        }
        val resultSource = entry.editedSuggestionInfo
                ?.let { RemoteInput.SOURCE_FREE_FORM_INPUT }
                ?: RemoteInput.SOURCE_CHOICE
        RemoteInput.setResultsSource(fillInIntent, resultSource)
        return fillInIntent
    }
}
+5 −7
Original line number Diff line number Diff line
@@ -114,15 +114,13 @@ public class RemoteInputViewTest extends SysuiTestCase {
        mContext.unregisterReceiver(mReceiver);
    }

    private void setTestPendingIntent(RemoteInputView view, RemoteInputViewController controller) {
    private void setTestPendingIntent(RemoteInputViewController controller) {
        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0,
                new Intent(TEST_ACTION), PendingIntent.FLAG_MUTABLE);
        RemoteInput input = new RemoteInput.Builder(TEST_RESULT_KEY).build();
        RemoteInput[] inputs = {input};

        view.setPendingIntent(pendingIntent);
        controller.setPendingIntent(pendingIntent);
        view.setRemoteInput(inputs, input, null /* editedSuggestionInfo */);
        controller.setRemoteInput(input);
        controller.setRemoteInputs(inputs);
    }
@@ -137,7 +135,7 @@ public class RemoteInputViewTest extends SysuiTestCase {
        RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
        RemoteInputViewController controller = bindController(view, row.getEntry());

        setTestPendingIntent(view, controller);
        setTestPendingIntent(controller);

        view.focus();

@@ -177,7 +175,7 @@ public class RemoteInputViewTest extends SysuiTestCase {
        RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
        RemoteInputViewController controller = bindController(view, row.getEntry());

        setTestPendingIntent(view, controller);
        setTestPendingIntent(controller);

        view.focus();

@@ -235,7 +233,7 @@ public class RemoteInputViewTest extends SysuiTestCase {
        RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
        RemoteInputViewController controller = bindController(view, row.getEntry());

        setTestPendingIntent(view, controller);
        setTestPendingIntent(controller);

        // Open view, send a reply
        view.focus();
@@ -265,7 +263,7 @@ public class RemoteInputViewTest extends SysuiTestCase {
        RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
        RemoteInputViewController controller = bindController(view, row.getEntry());

        setTestPendingIntent(view, controller);
        setTestPendingIntent(controller);

        // Open view, attach an image
        view.focus();