summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2018-10-10 11:10:33 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2018-10-10 11:10:33 +0000
commit515de0d6c2d589fa38c7e3af8f9d578bbb6bd15d (patch)
treeb2e0bad936087b3ad34820c6a11d95cba72e5c9a
parent8ef2ae924cbc1be43391f66089062237415697d6 (diff)
parent638430e76e813311c36197e6141810fda9d299fd (diff)
Merge "Fix and cleanup smart replies checking"
-rw-r--r--core/java/android/app/Notification.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java80
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java90
3 files changed, 159 insertions, 43 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 15893066b469..b57a7d982960 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -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.
*
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 4963a0c6ae01..4ef8dbb19318 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -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));
+ || entry.targetSdk >= Build.VERSION_CODES.P));
- boolean hasRemoteInput = false;
RemoteInput remoteInputWithChoices = null;
- PendingIntent pendingIntentWithChoices = 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 {
- choices = entry.smartReplies;
- }
- }
- if (showRemoteInputView || showSmartReplyView) {
- break;
- }
- }
- }
- }
-
- applyRemoteInput(entry, hasRemoteInput);
+ 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;
+ }
+
+ 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);
}
}
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java
index 9db823c0d3f5..55c16b367fab 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java
@@ -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);
+ }
}