Merge "[A11y] Notification Intelligence Feedback UI"
This commit is contained in:
@@ -112,11 +112,12 @@
|
||||
android:id="@+id/feedback"
|
||||
android:layout_width="@dimen/notification_feedback_size"
|
||||
android:layout_height="@dimen/notification_feedback_size"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginStart="@dimen/notification_header_separating_margin"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/ic_feedback_indicator"
|
||||
android:background="?android:selectableItemBackgroundBorderless"
|
||||
android:paddingTop="2dp"
|
||||
android:visibility="gone"
|
||||
android:contentDescription="@string/notification_feedback_indicator"
|
||||
/>
|
||||
|
||||
@@ -480,7 +480,7 @@
|
||||
<dimen name="notification_inbox_item_top_padding">5dp</dimen>
|
||||
|
||||
<!-- Size of the feedback indicator for notifications -->
|
||||
<dimen name="notification_feedback_size">16dp</dimen>
|
||||
<dimen name="notification_feedback_size">20dp</dimen>
|
||||
|
||||
<!-- Size of the profile badge for notifications -->
|
||||
<dimen name="notification_badge_size">12dp</dimen>
|
||||
|
||||
@@ -5366,6 +5366,14 @@
|
||||
<!-- Feedback Indicator -->
|
||||
<!-- Content description of the feedback icon in the notification. [CHAR LIMIT=NONE] -->
|
||||
<string name="notification_feedback_indicator">Provide Feedback</string>
|
||||
<!-- Content description of the alerted feedback icon in the notification. [CHAR LIMIT=NONE] -->
|
||||
<string name="notification_feedback_indicator_alerted">This notification was promoted to Default. Tap to provide feedback.</string>
|
||||
<!-- Content description of the silenced feedback icon in the notification. [CHAR LIMIT=NONE] -->
|
||||
<string name="notification_feedback_indicator_silenced">This notification was demoted to Silent. Tap to provide feedback.</string>
|
||||
<!-- Content description of the promoted feedback icon in the notification. [CHAR LIMIT=NONE] -->
|
||||
<string name="notification_feedback_indicator_promoted">This notification was ranked higher. Tap to provide feedback.</string>
|
||||
<!-- Content description of the demoted feedback icon in the notification. [CHAR LIMIT=NONE] -->
|
||||
<string name="notification_feedback_indicator_demoted">This notification was ranked lower. Tap to provide feedback.</string>
|
||||
|
||||
<!-- Dynamic mode battery saver strings -->
|
||||
<!-- The user visible name of the notification channel for the routine mode battery saver fyi notification [CHAR_LIMIT=80]-->
|
||||
|
||||
@@ -2252,6 +2252,10 @@
|
||||
<java-symbol type="string" name="ext_media_move_success_message" />
|
||||
<java-symbol type="string" name="ext_media_move_failure_title" />
|
||||
<java-symbol type="string" name="ext_media_move_failure_message" />
|
||||
<java-symbol type="string" name="notification_feedback_indicator_alerted" />
|
||||
<java-symbol type="string" name="notification_feedback_indicator_silenced" />
|
||||
<java-symbol type="string" name="notification_feedback_indicator_promoted" />
|
||||
<java-symbol type="string" name="notification_feedback_indicator_demoted" />
|
||||
<java-symbol type="style" name="Animation.RecentApplications" />
|
||||
<java-symbol type="integer" name="dock_enter_exit_duration" />
|
||||
<java-symbol type="bool" name="config_battery_percentage_setting_available" />
|
||||
|
||||
@@ -485,7 +485,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
|
||||
}
|
||||
}
|
||||
row.showFeedbackIcon(mAssistantFeedbackController.showFeedbackIndicator(entry),
|
||||
mAssistantFeedbackController.getFeedbackImageResource(entry));
|
||||
mAssistantFeedbackController.getFeedbackResources(entry));
|
||||
row.setLastAudiblyAlertedMs(entry.getLastAudiblyAlertedMs());
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
@@ -129,24 +130,28 @@ public class AssistantFeedbackController extends ContentObserver {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the feedback indicator image resource according to assistant's changes on this
|
||||
* notification's rank or importance.
|
||||
* Get the feedback indicator image and content description resources according to assistant's
|
||||
* changes on this notification's rank or importance.
|
||||
*
|
||||
* @param entry Notification Entry to show feedback for
|
||||
*/
|
||||
public int getFeedbackImageResource(NotificationEntry entry) {
|
||||
public Pair<Integer, Integer> getFeedbackResources(NotificationEntry entry) {
|
||||
int feedbackStatus = getFeedbackStatus(entry);
|
||||
switch (feedbackStatus) {
|
||||
case STATUS_ALERTED:
|
||||
return R.drawable.ic_feedback_alerted;
|
||||
return new Pair(R.drawable.ic_feedback_alerted,
|
||||
R.string.notification_feedback_indicator_alerted);
|
||||
case STATUS_SILENCED:
|
||||
return R.drawable.ic_feedback_silenced;
|
||||
return new Pair(R.drawable.ic_feedback_silenced,
|
||||
R.string.notification_feedback_indicator_silenced);
|
||||
case STATUS_PROMOTED:
|
||||
return R.drawable.ic_feedback_uprank;
|
||||
return new Pair(R.drawable.ic_feedback_uprank,
|
||||
R.string.notification_feedback_indicator_promoted);
|
||||
case STATUS_DEMOTED:
|
||||
return R.drawable.ic_feedback_downrank;
|
||||
return new Pair(R.drawable.ic_feedback_downrank,
|
||||
R.string.notification_feedback_indicator_demoted);
|
||||
default:
|
||||
return 0;
|
||||
return new Pair(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ import android.util.AttributeSet;
|
||||
import android.util.FloatProperty;
|
||||
import android.util.Log;
|
||||
import android.util.MathUtils;
|
||||
import android.util.Pair;
|
||||
import android.util.Property;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -1672,12 +1673,12 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
public void showFeedbackIcon(boolean show, int resId) {
|
||||
public void showFeedbackIcon(boolean show, Pair<Integer, Integer> resIds) {
|
||||
if (mIsSummaryWithChildren) {
|
||||
mChildrenContainer.showFeedbackIcon(show, resId);
|
||||
mChildrenContainer.showFeedbackIcon(show, resIds);
|
||||
}
|
||||
mPrivateLayout.showFeedbackIcon(show, resId);
|
||||
mPublicLayout.showFeedbackIcon(show, resId);
|
||||
mPrivateLayout.showFeedbackIcon(show, resIds);
|
||||
mPublicLayout.showFeedbackIcon(show, resIds);
|
||||
}
|
||||
|
||||
/** Sets the last time the notification being displayed audibly alerted the user. */
|
||||
|
||||
@@ -33,6 +33,7 @@ import android.provider.Settings;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.NotificationHeaderView;
|
||||
@@ -1586,15 +1587,15 @@ public class NotificationContentView extends FrameLayout {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void showFeedbackIcon(boolean show, int resId) {
|
||||
public void showFeedbackIcon(boolean show, Pair<Integer, Integer> resIds) {
|
||||
if (mContractedChild != null) {
|
||||
mContractedWrapper.showFeedbackIcon(show, resId);
|
||||
mContractedWrapper.showFeedbackIcon(show, resIds);
|
||||
}
|
||||
if (mExpandedChild != null) {
|
||||
mExpandedWrapper.showFeedbackIcon(show, resId);
|
||||
mExpandedWrapper.showFeedbackIcon(show, resIds);
|
||||
}
|
||||
if (mHeadsUpChild != null) {
|
||||
mHeadsUpWrapper.showFeedbackIcon(show, resId);
|
||||
mHeadsUpWrapper.showFeedbackIcon(show, resIds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Pair;
|
||||
import android.view.NotificationHeaderView;
|
||||
import android.view.NotificationTopLineView;
|
||||
import android.view.View;
|
||||
@@ -132,10 +133,13 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
|
||||
|
||||
/** Shows or hides feedback indicator */
|
||||
@Override
|
||||
public void showFeedbackIcon(boolean show, int resId) {
|
||||
public void showFeedbackIcon(boolean show, Pair<Integer, Integer> resIds) {
|
||||
mFeedbackIcon.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||
if (show && mFeedbackIcon instanceof ImageButton) {
|
||||
((ImageButton) mFeedbackIcon).setImageResource(resId);
|
||||
if (show) {
|
||||
if (mFeedbackIcon instanceof ImageButton) {
|
||||
((ImageButton) mFeedbackIcon).setImageResource(resIds.first);
|
||||
}
|
||||
mFeedbackIcon.setContentDescription(mView.getContext().getString(resIds.second));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.graphics.Rect;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.util.Pair;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.NotificationHeaderView;
|
||||
import android.view.View;
|
||||
@@ -103,7 +104,7 @@ public abstract class NotificationViewWrapper implements TransformableView {
|
||||
/**
|
||||
* Shows or hides feedback icon.
|
||||
*/
|
||||
public void showFeedbackIcon(boolean show, int resId) {
|
||||
public void showFeedbackIcon(boolean show, Pair<Integer, Integer> resIds) {
|
||||
}
|
||||
|
||||
public void onReinflated() {
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.content.res.Resources;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Pair;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.NotificationHeaderView;
|
||||
import android.view.View;
|
||||
@@ -1300,12 +1301,12 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
/**
|
||||
* Shows or hides feedback icon.
|
||||
*/
|
||||
public void showFeedbackIcon(boolean show, int resId) {
|
||||
public void showFeedbackIcon(boolean show, Pair<Integer, Integer> resIds) {
|
||||
if (mNotificationHeaderWrapper != null) {
|
||||
mNotificationHeaderWrapper.showFeedbackIcon(show, resId);
|
||||
mNotificationHeaderWrapper.showFeedbackIcon(show, resIds);
|
||||
}
|
||||
if (mNotificationHeaderWrapperLowPriority != null) {
|
||||
mNotificationHeaderWrapperLowPriority.showFeedbackIcon(show, resId);
|
||||
mNotificationHeaderWrapperLowPriority.showFeedbackIcon(show, resIds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ import android.provider.Settings;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
@@ -120,9 +121,9 @@ public class AssistantFeedbackControllerTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetFeedbackImageResource_settingDisabled() {
|
||||
public void testGetFeedbackResources_settingDisabled() {
|
||||
switchSetting(OFF);
|
||||
Assert.assertEquals(0, mAssistantFeedbackController.getFeedbackImageResource(
|
||||
Assert.assertEquals(new Pair(0, 0), mAssistantFeedbackController.getFeedbackResources(
|
||||
getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_UNCHANGED)));
|
||||
}
|
||||
|
||||
|
||||
@@ -39,10 +39,12 @@ import android.app.NotificationChannel;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.testing.TestableLooper.RunWithLooper;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
@@ -210,7 +212,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
|
||||
// public notification is custom layout - no header
|
||||
mGroupRow.setSensitive(true, true);
|
||||
mGroupRow.setOnFeedbackClickListener(null);
|
||||
mGroupRow.showFeedbackIcon(false, 0);
|
||||
mGroupRow.showFeedbackIcon(false, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -224,12 +226,13 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
|
||||
mGroupRow.setChildrenContainer(mockContainer);
|
||||
|
||||
final boolean show = true;
|
||||
final int resId = 1;
|
||||
mGroupRow.showFeedbackIcon(show, resId);
|
||||
final Pair<Integer, Integer> resIds = new Pair(R.drawable.ic_feedback_alerted,
|
||||
R.string.notification_feedback_indicator_alerted);
|
||||
mGroupRow.showFeedbackIcon(show, resIds);
|
||||
|
||||
verify(mockContainer, times(1)).showFeedbackIcon(show, resId);
|
||||
verify(privateLayout, times(1)).showFeedbackIcon(show, resId);
|
||||
verify(publicLayout, times(1)).showFeedbackIcon(show, resId);
|
||||
verify(mockContainer, times(1)).showFeedbackIcon(show, resIds);
|
||||
verify(privateLayout, times(1)).showFeedbackIcon(show, resIds);
|
||||
verify(publicLayout, times(1)).showFeedbackIcon(show, resIds);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.util.Pair;
|
||||
import android.view.NotificationHeaderView;
|
||||
import android.view.View;
|
||||
import android.view.ViewPropertyAnimator;
|
||||
@@ -33,6 +34,7 @@ import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.widget.NotificationExpandButton;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.media.dialog.MediaOutputDialogFactory;
|
||||
@@ -95,7 +97,8 @@ public class NotificationContentViewTest extends SysuiTestCase {
|
||||
mView.setExpandedChild(mockExpanded);
|
||||
mView.setHeadsUpChild(mockHeadsUp);
|
||||
|
||||
mView.showFeedbackIcon(true, 1);
|
||||
mView.showFeedbackIcon(true, new Pair(R.drawable.ic_feedback_alerted,
|
||||
R.string.notification_feedback_indicator_alerted));
|
||||
|
||||
verify(mockContracted, times(1)).setVisibility(View.VISIBLE);
|
||||
verify(mockExpanded, times(1)).setVisibility(View.VISIBLE);
|
||||
|
||||
Reference in New Issue
Block a user