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

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

Merge "Fix and cleanup smart replies checking"

parents 8ef2ae92 638430e7
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ import android.text.style.RelativeSizeSpan;
import android.text.style.TextAppearanceSpan;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import android.view.Gravity;
@@ -3129,6 +3130,37 @@ public class Notification implements Parcelable
        return false;
    }


    /**
     * Finds and returns a remote input and its corresponding action.
     *
     * @param requiresFreeform requires the remoteinput to allow freeform or not.
     * @return the result pair, {@code null} if no result is found.
     *
     * @hide
     */
    @Nullable
    public Pair<RemoteInput, Action> findRemoteInputActionPair(boolean requiresFreeform) {
        if (actions == null) {
            return null;
        }
        for (Notification.Action action : actions) {
            if (action.getRemoteInputs() == null) {
                continue;
            }
            RemoteInput resultRemoteInput = null;
            for (RemoteInput remoteInput : action.getRemoteInputs()) {
                if (remoteInput.getAllowFreeFormInput() || !requiresFreeform) {
                    resultRemoteInput = remoteInput;
                }
            }
            if (resultRemoteInput != null) {
                return Pair.create(resultRemoteInput, action);
            }
        }
        return null;
    }

    /**
     * Builder class for {@link Notification} objects.
     *
+37 −43
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.service.notification.StatusBarNotification;
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Pair;
import android.view.MotionEvent;
import android.view.NotificationHeaderView;
import android.view.View;
@@ -40,12 +41,12 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ContrastColorUtil;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationCustomViewWrapper;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationCustomViewWrapper;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.RemoteInputView;
@@ -1188,6 +1189,7 @@ public class NotificationContentView extends FrameLayout {
        updateSingleLineView();
        updateAmbientSingleLineView();
    }

    private void updateSingleLineView() {
        if (mIsChildInGroup) {
            boolean isNewView = mSingleLineView == null;
@@ -1223,53 +1225,44 @@ public class NotificationContentView extends FrameLayout {
            return;
        }

        boolean enableSmartReplies = (mSmartReplyConstants.isEnabled()
        Notification notification = entry.notification.getNotification();

        Pair<RemoteInput, Notification.Action> remoteInputActionPair =
                entry.notification.getNotification().findRemoteInputActionPair(false /*freeform */);
        Pair<RemoteInput, Notification.Action> freeformRemoteInputActionPair =
                notification.findRemoteInputActionPair(true /*freeform */);

        boolean enableAppGeneratedSmartReplies = (mSmartReplyConstants.isEnabled()
                && (!mSmartReplyConstants.requiresTargetingP()
                || entry.targetSdk >= Build.VERSION_CODES.P));

        boolean hasRemoteInput = false;
        RemoteInput remoteInputWithChoices = null;
        PendingIntent pendingIntentWithChoices= null;
        CharSequence[] choices = null;

        Notification.Action[] actions = entry.notification.getNotification().actions;
        if (actions != null) {
            for (Notification.Action a : actions) {
                if (a.getRemoteInputs() == null) {
                    continue;
                }
                for (RemoteInput ri : a.getRemoteInputs()) {
                    boolean showRemoteInputView = ri.getAllowFreeFormInput();
                    boolean showSmartReplyView = enableSmartReplies
                            && (ArrayUtils.isEmpty(ri.getChoices())
                            || (showRemoteInputView && !ArrayUtils.isEmpty(entry.smartReplies)));
                    if (showRemoteInputView) {
                        hasRemoteInput = true;
                    }
                    if (showSmartReplyView) {
                        remoteInputWithChoices = ri;
                        pendingIntentWithChoices = a.actionIntent;
                        if (!ArrayUtils.isEmpty(ri.getChoices())) {
                            choices = ri.getChoices();
                        } else {
        if (enableAppGeneratedSmartReplies
                && remoteInputActionPair != null
                && !ArrayUtils.isEmpty(remoteInputActionPair.first.getChoices())) {
            // app generated smart replies
            remoteInputWithChoices = remoteInputActionPair.first;
            pendingIntentWithChoices = remoteInputActionPair.second.actionIntent;
            choices = remoteInputActionPair.first.getChoices();
        } else if (!ArrayUtils.isEmpty(entry.smartReplies)
                && freeformRemoteInputActionPair != null
                && freeformRemoteInputActionPair.second.getAllowGeneratedReplies()) {
            // system generated smart replies
            remoteInputWithChoices = freeformRemoteInputActionPair.first;
            pendingIntentWithChoices = freeformRemoteInputActionPair.second.actionIntent;
            choices = entry.smartReplies;
        }
                    }
                    if (showRemoteInputView || showSmartReplyView) {
                        break;
                    }
                }
            }
        }

        applyRemoteInput(entry, hasRemoteInput);
        applyRemoteInput(entry, freeformRemoteInputActionPair != null);
        applySmartReplyView(remoteInputWithChoices, pendingIntentWithChoices, entry, choices);
    }

    private void applyRemoteInput(NotificationData.Entry entry, boolean hasRemoteInput) {
    private void applyRemoteInput(NotificationData.Entry entry, boolean hasFreeformRemoteInput) {
        View bigContentView = mExpandedChild;
        if (bigContentView != null) {
            mExpandedRemoteInput = applyRemoteInput(bigContentView, entry, hasRemoteInput,
            mExpandedRemoteInput = applyRemoteInput(bigContentView, entry, hasFreeformRemoteInput,
                    mPreviousExpandedRemoteInputIntent, mCachedExpandedRemoteInput,
                    mExpandedWrapper);
        } else {
@@ -1284,7 +1277,8 @@ public class NotificationContentView extends FrameLayout {

        View headsUpContentView = mHeadsUpChild;
        if (headsUpContentView != null) {
            mHeadsUpRemoteInput = applyRemoteInput(headsUpContentView, entry, hasRemoteInput,
            mHeadsUpRemoteInput = applyRemoteInput(
                    headsUpContentView, entry, hasFreeformRemoteInput,
                    mPreviousHeadsUpRemoteInputIntent, mCachedHeadsUpRemoteInput, mHeadsUpWrapper);
        } else {
            mHeadsUpRemoteInput = null;
@@ -1370,8 +1364,8 @@ public class NotificationContentView extends FrameLayout {
            mExpandedSmartReplyView =
                    applySmartReplyView(mExpandedChild, remoteInput, pendingIntent, entry, choices);
            if (mExpandedSmartReplyView != null && remoteInput != null
                    && remoteInput.getChoices() != null && remoteInput.getChoices().length > 0) {
                mSmartReplyController.smartRepliesAdded(entry, remoteInput.getChoices().length);
                    && choices != null && choices.length > 0) {
                mSmartReplyController.smartRepliesAdded(entry, choices.length);
            }
        }
    }
+90 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import android.support.test.runner.AndroidJUnit4;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.StyleSpan;
import android.util.Pair;
import android.widget.RemoteViews;

import com.android.server.UiServiceTestCase;
@@ -541,5 +542,94 @@ public class NotificationTest extends UiServiceTestCase {

        assertFalse(Notification.areActionsVisiblyDifferent(n1, n2));
    }

    @Test
    public void testFreeformRemoteInputActionPair_noRemoteInput() {
        PendingIntent intent = mock(PendingIntent.class);
        Icon icon = mock(Icon.class);
        Notification notification = new Notification.Builder(mContext, "test")
                .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent)
                        .build())
                .build();
        assertNull(notification.findRemoteInputActionPair(false));
    }

    @Test
    public void testFreeformRemoteInputActionPair_hasRemoteInput() {
        PendingIntent intent = mock(PendingIntent.class);
        Icon icon = mock(Icon.class);

        RemoteInput remoteInput = new RemoteInput.Builder("a").build();

        Notification.Action actionWithRemoteInput =
                new Notification.Action.Builder(icon, "TEXT 1", intent)
                        .addRemoteInput(remoteInput)
                        .addRemoteInput(remoteInput)
                        .build();

        Notification.Action actionWithoutRemoteInput =
                new Notification.Action.Builder(icon, "TEXT 2", intent)
                        .build();

        Notification notification = new Notification.Builder(mContext, "test")
                .addAction(actionWithoutRemoteInput)
                .addAction(actionWithRemoteInput)
                .build();

        Pair<RemoteInput, Notification.Action> remoteInputActionPair =
                notification.findRemoteInputActionPair(false);

        assertNotNull(remoteInputActionPair);
        assertEquals(remoteInput, remoteInputActionPair.first);
        assertEquals(actionWithRemoteInput, remoteInputActionPair.second);
    }

    @Test
    public void testFreeformRemoteInputActionPair_requestFreeform_noFreeformRemoteInput() {
        PendingIntent intent = mock(PendingIntent.class);
        Icon icon = mock(Icon.class);
        Notification notification = new Notification.Builder(mContext, "test")
                .addAction(new Notification.Action.Builder(icon, "TEXT 1", intent)
                        .addRemoteInput(
                                new RemoteInput.Builder("a")
                                        .setAllowFreeFormInput(false).build())
                        .build())
                .build();
        assertNull(notification.findRemoteInputActionPair(true));
    }

    @Test
    public void testFreeformRemoteInputActionPair_requestFreeform_hasFreeformRemoteInput() {
        PendingIntent intent = mock(PendingIntent.class);
        Icon icon = mock(Icon.class);

        RemoteInput remoteInput =
                new RemoteInput.Builder("a").setAllowFreeFormInput(false).build();
        RemoteInput freeformRemoteInput =
                new RemoteInput.Builder("b").setAllowFreeFormInput(true).build();

        Notification.Action actionWithFreeformRemoteInput =
                new Notification.Action.Builder(icon, "TEXT 1", intent)
                        .addRemoteInput(remoteInput)
                        .addRemoteInput(freeformRemoteInput)
                        .build();

        Notification.Action actionWithoutFreeformRemoteInput =
                new Notification.Action.Builder(icon, "TEXT 2", intent)
                        .addRemoteInput(remoteInput)
                        .build();

        Notification notification = new Notification.Builder(mContext, "test")
                .addAction(actionWithoutFreeformRemoteInput)
                .addAction(actionWithFreeformRemoteInput)
                .build();

        Pair<RemoteInput, Notification.Action> remoteInputActionPair =
                notification.findRemoteInputActionPair(true);

        assertNotNull(remoteInputActionPair);
        assertEquals(freeformRemoteInput, remoteInputActionPair.first);
        assertEquals(actionWithFreeformRemoteInput, remoteInputActionPair.second);
    }
}