diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index 8223d9717208e..a03fc136da614 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.row; +import static android.app.Notification.Action.SEMANTIC_ACTION_MARK_CONVERSATION_AS_PRIORITY; import static android.service.notification.NotificationListenerService.REASON_CANCEL; import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters; @@ -1785,6 +1786,27 @@ public class ExpandableNotificationRow extends ActivatableNotificationView doLongClickCallback(x, y, menuItem); } + /** + * Perform a smart action which triggers a longpress (expose guts). + * Based on the semanticAction passed, may update the state of the guts view. + * @param semanticAction associated with this smart action click + */ + public void doSmartActionClick(int x, int y, int semanticAction) { + createMenu(); + NotificationMenuRowPlugin provider = getProvider(); + MenuItem menuItem = null; + if (provider != null) { + menuItem = provider.getLongpressMenuItem(mContext); + } + if (SEMANTIC_ACTION_MARK_CONVERSATION_AS_PRIORITY == semanticAction + && menuItem.getGutsView() instanceof NotificationConversationInfo) { + NotificationConversationInfo info = + (NotificationConversationInfo) menuItem.getGutsView(); + info.setSelectedAction(NotificationConversationInfo.ACTION_FAVORITE); + } + doLongClickCallback(x, y, menuItem); + } + private void doLongClickCallback(int x, int y, MenuItem menuItem) { if (mLongPressListener != null && menuItem != null) { mLongPressListener.onLongPress(this, x, y, menuItem); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java index 1a2550b818789..adeba9078c52a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java @@ -206,6 +206,7 @@ public class NotificationConversationInfo extends LinearLayout implements } public void bindNotification( + @Action int selectedAction, ShortcutManager shortcutManager, PackageManager pm, INotificationManager iNotificationManager, @@ -224,7 +225,8 @@ public class NotificationConversationInfo extends LinearLayout implements @Background Handler bgHandler, OnConversationSettingsClickListener onConversationSettingsClickListener, Optional bubblesManagerOptional) { - mSelectedAction = -1; + mPressedApply = false; + mSelectedAction = selectedAction; mINotificationManager = iNotificationManager; mOnUserInteractionCallback = onUserInteractionCallback; mPackageName = pkg; @@ -297,7 +299,8 @@ public class NotificationConversationInfo extends LinearLayout implements settingsButton.setOnClickListener(getSettingsOnClickListener()); settingsButton.setVisibility(settingsButton.hasOnClickListeners() ? VISIBLE : GONE); - updateToggleActions(getSelectedAction(), false); + updateToggleActions(mSelectedAction == -1 ? getPriority() : mSelectedAction, + false); } private void bindHeader() { @@ -406,7 +409,7 @@ public class NotificationConversationInfo extends LinearLayout implements @Override public void onFinishedClosing() { - // TODO: do we need to do anything here? + mSelectedAction = -1; } @Override @@ -487,7 +490,7 @@ public class NotificationConversationInfo extends LinearLayout implements throw new IllegalArgumentException("Unrecognized behavior: " + mSelectedAction); } - boolean isAChange = getSelectedAction() != selectedAction; + boolean isAChange = getPriority() != selectedAction; TextView done = findViewById(R.id.done); done.setText(isAChange ? R.string.inline_ok_button @@ -498,6 +501,10 @@ public class NotificationConversationInfo extends LinearLayout implements } int getSelectedAction() { + return mSelectedAction; + } + + private int getPriority() { if (mNotificationChannel.getImportance() <= IMPORTANCE_LOW && mNotificationChannel.getImportance() > IMPORTANCE_UNSPECIFIED) { return ACTION_MUTE; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java index 2fd17a5876127..6a873b678a93b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java @@ -474,6 +474,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx R.dimen.notification_guts_conversation_icon_size)); notificationInfoView.bindNotification( + notificationInfoView.getSelectedAction(), mShortcutManager, pmUser, mNotificationManager, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartRepliesAndActionsInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartRepliesAndActionsInflater.kt index 6a3a69c0419ec..ea803253ea0f0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartRepliesAndActionsInflater.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartRepliesAndActionsInflater.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.policy import android.app.Notification +import android.app.Notification.Action.SEMANTIC_ACTION_MARK_CONVERSATION_AS_PRIORITY import android.app.PendingIntent import android.app.RemoteInput import android.content.Context @@ -310,11 +311,19 @@ interface SmartActionInflater { actionIndex: Int, action: Notification.Action ) = + if (smartActions.fromAssistant + && SEMANTIC_ACTION_MARK_CONVERSATION_AS_PRIORITY == action.semanticAction) { + entry.row.doSmartActionClick(entry.row.x.toInt() / 2, + entry.row.y.toInt() / 2, SEMANTIC_ACTION_MARK_CONVERSATION_AS_PRIORITY) + smartReplyController + .smartActionClicked(entry, actionIndex, action, smartActions.fromAssistant) + } else { activityStarter.startPendingIntentDismissingKeyguard(action.actionIntent, entry.row) { smartReplyController - .smartActionClicked(entry, actionIndex, action, smartActions.fromAssistant) + .smartActionClicked(entry, actionIndex, action, smartActions.fromAssistant) headsUpManager.removeNotification(entry.key, true /* releaseImmediately */) } + } } interface SmartReplyInflater { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java index 291b223d72bb5..5c37656d2cf1f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java @@ -241,6 +241,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { @Test public void testBindNotification_SetsShortcutIcon() { mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -265,6 +266,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { public void testBindNotification_SetsTextApplicationName() { when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name"); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -289,6 +291,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { @Test public void testBindNotification_SetsTextChannelName() { mNotificationInfo.bindNotification( + -1, mShortcutManager, mLauncherApps, mMockPackageManager, @@ -316,6 +319,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mConversationChannel.setGroup(group.getId()); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -341,6 +345,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { @Test public void testBindNotification_GroupNameHiddenIfNoGroup() { mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -365,6 +370,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { @Test public void testBindNotification_noDelegate() { mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -400,6 +406,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { .setShortcutInfo(mShortcutInfo) .build(); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -425,6 +432,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { public void testBindNotification_SetsOnClickListenerForSettings() { final CountDownLatch latch = new CountDownLatch(1); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -454,6 +462,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { @Test public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() { mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -478,6 +487,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { public void testBindNotification_SettingsButtonInvisibleWhenDeviceUnprovisioned() { final CountDownLatch latch = new CountDownLatch(1); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -506,6 +516,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mConversationChannel.setImportance(IMPORTANCE_LOW); mConversationChannel.setImportantConversation(true); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -534,6 +545,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mConversationChannel.setImportantConversation(false); mConversationChannel.setAllowBubbles(true); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -565,6 +577,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mConversationChannel.setImportantConversation(false); mConversationChannel.setAllowBubbles(true); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -595,6 +608,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mConversationChannel.setImportantConversation(false); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -639,6 +653,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mConversationChannel.setImportance(IMPORTANCE_LOW); mConversationChannel.setImportantConversation(false); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -682,6 +697,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mConversationChannel.setImportantConversation(false); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -726,6 +742,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mConversationChannel.setImportantConversation(false); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -763,6 +780,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mConversationChannel.setImportance(9); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -799,6 +817,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mConversationChannel.setImportantConversation(true); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -831,12 +850,76 @@ public class NotificationConversationInfoTest extends SysuiTestCase { assertTrue(captor.getValue().isImportantConversation()); } + @Test + public void testDefaultSelectedWhenChannelIsDefault() throws Exception { + // GIVEN channel importance indicates "Default" priority + mConversationChannel.setImportance(IMPORTANCE_HIGH); + mConversationChannel.setImportantConversation(false); + + // WHEN we indicate no selected action + mNotificationInfo.bindNotification( + -1, // no action selected by default + mShortcutManager, + mMockPackageManager, + mMockINotificationManager, + mOnUserInteractionCallback, + TEST_PACKAGE_NAME, + mNotificationChannel, + mEntry, + mBubbleMetadata, + null, + null, + mIconFactory, + mContext, + mBuilderProvider, + true, + mTestHandler, + mTestHandler, null, Optional.of(mBubblesManager)); + + // THEN the selected action is -1, so the selected option is "Default" priority + assertEquals(mNotificationInfo.getSelectedAction(), -1); + assertTrue(mNotificationInfo.findViewById(R.id.default_behavior).isSelected()); + } + + @Test + public void testFavoriteSelectedWhenChannelIsDefault() throws Exception { + // GIVEN channel importance indicates "Default" priority + mConversationChannel.setImportance(IMPORTANCE_HIGH); + mConversationChannel.setImportantConversation(false); + + // WHEN we indicate the selected action should be "Favorite" + mNotificationInfo.bindNotification( + NotificationConversationInfo.ACTION_FAVORITE, // "Favorite" selected by default + mShortcutManager, + mMockPackageManager, + mMockINotificationManager, + mOnUserInteractionCallback, + TEST_PACKAGE_NAME, + mNotificationChannel, + mEntry, + mBubbleMetadata, + null, + null, + mIconFactory, + mContext, + mBuilderProvider, + true, + mTestHandler, + mTestHandler, null, Optional.of(mBubblesManager)); + + // THEN the selected action is "Favorite", so the selected option is "priority" priority + assertEquals(mNotificationInfo.getSelectedAction(), + NotificationConversationInfo.ACTION_FAVORITE); + assertTrue(mNotificationInfo.findViewById(R.id.priority).isSelected()); + } + @Test public void testDefault_andSave() throws Exception { mConversationChannel.setAllowBubbles(true); mConversationChannel.setOriginalImportance(IMPORTANCE_HIGH); mConversationChannel.setImportantConversation(true); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -873,6 +956,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mConversationChannel.setOriginalImportance(IMPORTANCE_HIGH); mConversationChannel.setImportantConversation(false); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -909,6 +993,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mConversationChannel.setOriginalImportance(IMPORTANCE_HIGH); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -944,6 +1029,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { mConversationChannel.setAllowBubbles(true); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -978,6 +1064,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { @Test public void testBindNotification_createsNewChannel() throws Exception { mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -1003,6 +1090,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { public void testBindNotification_doesNotCreateNewChannelIfExists() throws Exception { mNotificationChannel.setConversationId("", CONVERSATION_ID); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -1038,6 +1126,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { // GIVEN the user is changing conversation settings mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager, @@ -1078,6 +1167,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase { when(b.build()).thenReturn(controller); mNotificationInfo.bindNotification( + -1, mShortcutManager, mMockPackageManager, mMockINotificationManager,