Notification Intelligence Feedback UI Change

1. Remove OK button
2. If user taps Yes, closes dialog and if user taps No, redirects to
long press setting

Test: atest FeedbackInfoTest
Bug: 173460479
Change-Id: Idee79a0b28f480a51bf11bc0d31e836cf3eba9fc
This commit is contained in:
Chloris Kuo
2020-11-18 20:22:43 -08:00
parent aeca95853e
commit a4e0a02fe3
4 changed files with 68 additions and 57 deletions

View File

@@ -109,24 +109,4 @@
style="@style/TextAppearance.NotificationInfo.Button"/>
</LinearLayout>
<!-- Done button -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/notification_guts_button_spacing"
android:layout_marginBottom="@dimen/notification_guts_button_spacing"
android:gravity="end"
android:orientation="horizontal">
<TextView
android:id="@+id/ok"
android:text="@string/feedback_ok"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@drawable/ripple_drawable"
android:minWidth="48dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="-8dp"
style="@style/TextAppearance.NotificationInfo.Button"/>
</LinearLayout>
</com.android.systemui.statusbar.notification.row.FeedbackInfo>

View File

@@ -19,7 +19,6 @@ package com.android.systemui.statusbar.notification.row;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.service.notification.NotificationListenerService.Ranking.RANKING_DEMOTED;
import static android.service.notification.NotificationListenerService.Ranking.RANKING_PROMOTED;
import static android.service.notification.NotificationListenerService.Ranking.RANKING_UNCHANGED;
import android.annotation.SuppressLint;
import android.app.Notification;
@@ -43,6 +42,7 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.statusbar.notification.AssistantFeedbackController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -64,6 +64,9 @@ public class FeedbackInfo extends LinearLayout implements NotificationGuts.GutsC
private NotificationEntryManager mNotificationEntryManager;
private IStatusBarService mStatusBarService;
private AssistantFeedbackController mFeedbackController;
private NotificationGutsManager mNotificationGutsManager;
private NotificationMenuRowPlugin mMenuRowPlugin;
private ExpandableNotificationRow mExpandableNotificationRow;
public FeedbackInfo(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -73,19 +76,21 @@ public class FeedbackInfo extends LinearLayout implements NotificationGuts.GutsC
final PackageManager pm,
final StatusBarNotification sbn,
final NotificationEntry entry,
final ExpandableNotificationRow row,
final AssistantFeedbackController controller) {
mPkg = sbn.getPackageName();
mPm = pm;
mEntry = entry;
mExpandableNotificationRow = row;
mRanking = entry.getRanking();
mFeedbackController = controller;
mAppName = mPkg;
mNotificationEntryManager = Dependency.get(NotificationEntryManager.class);
mStatusBarService = Dependency.get(IStatusBarService.class);
mNotificationGutsManager = Dependency.get(NotificationGutsManager.class);
bindHeader();
bindPrompt();
bindButton();
}
private void bindHeader() {
@@ -161,27 +166,24 @@ public class FeedbackInfo extends LinearLayout implements NotificationGuts.GutsC
return sb.toString();
}
private void bindButton() {
TextView ok = findViewById(R.id.ok);
ok.setOnClickListener(this::closeControls);
}
private void positiveFeedback(View v) {
mGutsContainer.closeControls(v, false);
handleFeedback(true);
}
private void negativeFeedback(View v) {
mMenuRowPlugin = mExpandableNotificationRow.getProvider();
NotificationMenuRowPlugin.MenuItem menuItem = null;
if (mMenuRowPlugin != null) {
menuItem = mMenuRowPlugin.getLongpressMenuItem(mContext);
}
mGutsContainer.closeControls(v, false);
mNotificationGutsManager.openGuts(mExpandableNotificationRow, 0, 0, menuItem);
handleFeedback(false);
}
private void handleFeedback(boolean positive) {
TextView prompt = findViewById(R.id.prompt);
prompt.setText(mContext.getString(R.string.feedback_response));
TextView yes = findViewById(R.id.yes);
yes.setVisibility(View.GONE);
TextView no = findViewById(R.id.no);
no.setVisibility(View.GONE);
Bundle feedback = new Bundle();
feedback.putBoolean(FEEDBACK_KEY, positive);
sendFeedbackToAssistant(feedback);

View File

@@ -324,7 +324,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
userHandle.getIdentifier());
if (mAssistantFeedbackController.showFeedbackIndicator(row.getEntry())) {
feedbackInfo.bindGuts(pmUser, sbn, row.getEntry(), mAssistantFeedbackController);
feedbackInfo.bindGuts(pmUser, sbn, row.getEntry(), row, mAssistantFeedbackController);
}
}

View File

@@ -28,7 +28,6 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.eq;
@@ -56,6 +55,7 @@ import android.widget.TextView;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.statusbar.notification.AssistantFeedbackController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -65,8 +65,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import java.util.concurrent.CountDownLatch;
import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -78,18 +77,24 @@ public class FeedbackInfoTest extends SysuiTestCase {
private FeedbackInfo mFeedbackInfo;
private final PackageManager mMockPackageManager = mock(PackageManager.class);
private final NotificationGuts mGutsParent = mock(NotificationGuts.class);
private final ExpandableNotificationRow mMockNotificationRow =
mock(ExpandableNotificationRow.class);
private StatusBarNotification mSbn;
@Mock
private NotificationEntryManager mNotificationEntryManager;
@Mock
private IStatusBarService mStatusBarService;
@Mock
private NotificationGutsManager mNotificationGutsManager;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mDependency.injectTestDependency(NotificationEntryManager.class, mNotificationEntryManager);
mDependency.injectTestDependency(IStatusBarService.class, mStatusBarService);
mDependency.injectTestDependency(NotificationGutsManager.class, mNotificationGutsManager);
// Inflate the layout
final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
@@ -108,13 +113,14 @@ public class FeedbackInfoTest extends SysuiTestCase {
mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
new Notification(), UserHandle.CURRENT, null, 0);
}
@Test
public void testBindNotification_SetsTextApplicationName() {
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(),
mock(AssistantFeedbackController.class));
mMockNotificationRow, mock(AssistantFeedbackController.class));
final TextView textView = mFeedbackInfo.findViewById(R.id.pkg_name);
assertTrue(textView.getText().toString().contains("App Name"));
}
@@ -125,27 +131,16 @@ public class FeedbackInfoTest extends SysuiTestCase {
when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
.thenReturn(iconDrawable);
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(),
mock(AssistantFeedbackController.class));
mMockNotificationRow, mock(AssistantFeedbackController.class));
final ImageView iconView = mFeedbackInfo.findViewById(R.id.pkg_icon);
assertEquals(iconDrawable, iconView.getDrawable());
}
@Test
public void testOk() {
final CountDownLatch latch = new CountDownLatch(1);
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(),
mock(AssistantFeedbackController.class));
final View okButton = mFeedbackInfo.findViewById(R.id.ok);
okButton.performClick();
assertEquals(1, latch.getCount());
verify(mGutsParent, times(1)).closeControls(any(), anyBoolean());
}
@Test
public void testPrompt_silenced() {
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT,
IMPORTANCE_LOW, RANKING_UNCHANGED), mock(AssistantFeedbackController.class));
IMPORTANCE_LOW, RANKING_UNCHANGED), mMockNotificationRow,
mock(AssistantFeedbackController.class));
TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
assertEquals("This notification was silenced by the system. Was this correct?",
prompt.getText());
@@ -154,7 +149,8 @@ public class FeedbackInfoTest extends SysuiTestCase {
@Test
public void testPrompt_promoted_importance() {
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT,
IMPORTANCE_HIGH, RANKING_UNCHANGED), mock(AssistantFeedbackController.class));
IMPORTANCE_HIGH, RANKING_UNCHANGED), mMockNotificationRow,
mock(AssistantFeedbackController.class));
TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
assertEquals("This notification was promoted by the system. Was this correct?",
prompt.getText());
@@ -163,7 +159,8 @@ public class FeedbackInfoTest extends SysuiTestCase {
@Test
public void testPrompt_promoted_ranking() {
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT,
IMPORTANCE_DEFAULT, RANKING_PROMOTED), mock(AssistantFeedbackController.class));
IMPORTANCE_DEFAULT, RANKING_PROMOTED), mMockNotificationRow,
mock(AssistantFeedbackController.class));
TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
assertEquals("This notification was promoted by the system. Was this correct?",
prompt.getText());
@@ -172,7 +169,8 @@ public class FeedbackInfoTest extends SysuiTestCase {
@Test
public void testPrompt_demoted_importance() {
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_LOW,
IMPORTANCE_MIN, RANKING_UNCHANGED), mock(AssistantFeedbackController.class));
IMPORTANCE_MIN, RANKING_UNCHANGED), mMockNotificationRow,
mock(AssistantFeedbackController.class));
TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
assertEquals("This notification was demoted by the system. Was this correct?",
prompt.getText());
@@ -181,12 +179,43 @@ public class FeedbackInfoTest extends SysuiTestCase {
@Test
public void testPrompt_demoted_ranking() {
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT,
IMPORTANCE_DEFAULT, RANKING_DEMOTED), mock(AssistantFeedbackController.class));
IMPORTANCE_DEFAULT, RANKING_DEMOTED), mMockNotificationRow,
mock(AssistantFeedbackController.class));
TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
assertEquals("This notification was demoted by the system. Was this correct?",
prompt.getText());
}
@Test
public void testPositiveFeedback() {
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
mock(AssistantFeedbackController.class));
final View yes = mFeedbackInfo.findViewById(R.id.yes);
yes.performClick();
verify(mGutsParent, times(1)).closeControls(yes, false);
}
@Test
public void testNegativeFeedback() {
when(mNotificationGutsManager.openGuts(
any(View.class),
anyInt(),
anyInt(),
any(NotificationMenuRowPlugin.MenuItem.class)))
.thenReturn(true);
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
mock(AssistantFeedbackController.class));
final View no = mFeedbackInfo.findViewById(R.id.no);
no.performClick();
verify(mGutsParent, times(1)).closeControls(no, false);
verify(mNotificationGutsManager, times(1)).openGuts(
eq(mMockNotificationRow), eq(0), eq(0),
any());
}
private NotificationEntry getEntry(int oldImportance, int newImportance,
int rankingAdjustment) {
NotificationChannel channel = new NotificationChannel("id", "name", oldImportance);