Merge "Conversation inline controls redesign" into rvc-dev

This commit is contained in:
TreeHugger Robot
2020-03-20 22:40:34 +00:00
committed by Android (Google) Code Review
6 changed files with 675 additions and 586 deletions

View File

@@ -53,8 +53,7 @@
android:layout_centerVertical="true"
android:gravity="center_vertical"
android:layout_alignEnd="@id/conversation_icon"
android:layout_toEndOf="@id/conversation_icon"
android:layout_alignStart="@id/mute">
android:layout_toEndOf="@id/conversation_icon">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -127,96 +126,230 @@
<!-- end aligned fields -->
<ImageButton
android:id="@+id/mute"
android:layout_width="@dimen/notification_importance_toggle_size"
android:layout_height="@dimen/notification_importance_toggle_size"
android:layout_centerVertical="true"
android:background="@drawable/ripple_drawable"
android:layout_toStartOf="@id/fave"
android:tint="@color/notification_guts_link_icon_tint"/>
<ImageButton
android:id="@+id/fave"
android:id="@+id/info"
android:layout_width="@dimen/notification_importance_toggle_size"
android:layout_height="@dimen/notification_importance_toggle_size"
android:layout_centerVertical="true"
android:background="@drawable/ripple_drawable"
android:contentDescription="@string/notification_more_settings"
android:src="@drawable/ic_settings"
android:layout_alignParentEnd="true"
android:tint="@color/notification_guts_link_icon_tint"/>
</LinearLayout>
<LinearLayout
android:id="@+id/actions"
android:id="@+id/inline_controls"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="@*android:dimen/notification_content_margin_end"
android:paddingEnd="@*android:dimen/notification_content_margin_end"
android:layout_marginTop="@dimen/notification_guts_option_vertical_padding"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical">
<View
<!-- Non configurable app/channel text. appears instead of @+id/interruptiveness_settings-->
<TextView
android:id="@+id/non_configurable_text"
android:text="@string/notification_unblockable_desc"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="@color/GM2_grey_300" />
android:layout_height="wrap_content"
style="@*android:style/TextAppearance.DeviceDefault.Notification" />
<Button
android:id="@+id/snooze"
android:layout_height="@dimen/notification_guts_conversation_action_height"
<!-- Non configurable multichannel text. appears instead of @+id/interruptiveness_settings-->
<TextView
android:id="@+id/non_configurable_multichannel_text"
android:text="@string/notification_multichannel_desc"
android:visibility="gone"
android:layout_width="match_parent"
style="?android:attr/borderlessButtonStyle"
android:text="@string/notification_menu_snooze_action"
android:gravity="left|center_vertical"
android:drawableStart="@drawable/ic_snooze"
android:drawablePadding="@dimen/notification_guts_conversation_action_text_padding_start"
android:drawableTint="@color/notification_guts_link_icon_tint"/>
android:layout_height="wrap_content"
style="@*android:style/TextAppearance.DeviceDefault.Notification" />
<View
<LinearLayout
android:id="@+id/interruptiveness_settings"
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="@color/GM2_grey_300" />
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="@+id/bubble"
android:layout_height="@dimen/notification_guts_conversation_action_height"
android:layout_width="match_parent"
style="?android:attr/borderlessButtonStyle"
android:text="@string/notification_conversation_favorite"
android:gravity="left|center_vertical"
android:drawableStart="@drawable/ic_create_bubble"
android:drawablePadding="@dimen/notification_guts_conversation_action_text_padding_start"
android:drawableTint="@color/notification_guts_link_icon_tint"/>
<com.android.systemui.statusbar.notification.row.ButtonLinearLayout
android:id="@+id/priority"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/notification_importance_button_padding"
android:clickable="true"
android:focusable="true"
android:background="@drawable/notification_guts_priority_button_bg"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
>
<ImageView
android:id="@+id/priority_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_important_outline"
android:background="@android:color/transparent"
android:tint="@color/notification_guts_priority_contents"
android:clickable="false"
android:focusable="false"/>
<TextView
android:id="@+id/priority_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/notification_importance_drawable_padding"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
android:clickable="false"
android:focusable="false"
android:textAppearance="@style/TextAppearance.NotificationImportanceButton"
android:text="@string/notification_priority_title"/>
</LinearLayout>
<TextView
android:id="@+id/priority_summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/notification_importance_button_description_top_margin"
android:visibility="gone"
android:text="@string/notification_channel_summary_priority"
android:clickable="false"
android:focusable="false"
android:ellipsize="end"
android:maxLines="2"
android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"/>
</com.android.systemui.statusbar.notification.row.ButtonLinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="@color/GM2_grey_300" />
<Button
android:id="@+id/home"
android:layout_height="@dimen/notification_guts_conversation_action_height"
android:layout_width="match_parent"
style="?android:attr/borderlessButtonStyle"
android:text="@string/notification_conversation_home_screen"
android:gravity="left|center_vertical"
android:drawableStart="@drawable/ic_add_to_home"
android:drawablePadding="@dimen/notification_guts_conversation_action_text_padding_start"
android:drawableTint="@color/notification_guts_link_icon_tint"/>
<com.android.systemui.statusbar.notification.row.ButtonLinearLayout
android:id="@+id/default_behavior"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/notification_importance_button_separation"
android:padding="@dimen/notification_importance_button_padding"
android:clickable="true"
android:focusable="true"
android:background="@drawable/notification_guts_priority_button_bg"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
>
<ImageView
android:id="@+id/default_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_notifications_alert"
android:background="@android:color/transparent"
android:tint="@color/notification_guts_priority_contents"
android:clickable="false"
android:focusable="false"/>
<TextView
android:id="@+id/default_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/notification_importance_drawable_padding"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
android:clickable="false"
android:focusable="false"
android:textAppearance="@style/TextAppearance.NotificationImportanceButton"
android:text="@string/notification_alert_title"/>
</LinearLayout>
<TextView
android:id="@+id/default_summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/notification_importance_button_description_top_margin"
android:visibility="gone"
android:text="@string/notification_channel_summary_default"
android:clickable="false"
android:focusable="false"
android:ellipsize="end"
android:maxLines="2"
android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"/>
</com.android.systemui.statusbar.notification.row.ButtonLinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="@color/GM2_grey_300" />
<Button
android:id="@+id/info"
android:layout_height="@dimen/notification_guts_conversation_action_height"
android:layout_width="match_parent"
style="?android:attr/borderlessButtonStyle"
android:drawableStart="@drawable/ic_settings"
android:text="@string/notification_menu_settings_action"
android:gravity="left|center_vertical"
android:drawablePadding="@dimen/notification_guts_conversation_action_text_padding_start"
android:drawableTint="@color/notification_guts_link_icon_tint"/>
<com.android.systemui.statusbar.notification.row.ButtonLinearLayout
android:id="@+id/silence"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/notification_importance_button_separation"
android:padding="@dimen/notification_importance_button_padding"
android:clickable="true"
android:focusable="true"
android:background="@drawable/notification_guts_priority_button_bg"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
>
<ImageView
android:id="@+id/silence_icon"
android:src="@drawable/ic_notifications_silence"
android:background="@android:color/transparent"
android:tint="@color/notification_guts_priority_contents"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"/>
<TextView
android:id="@+id/silence_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:clickable="false"
android:focusable="false"
android:layout_toEndOf="@id/silence_icon"
android:layout_marginStart="@dimen/notification_importance_drawable_padding"
android:textAppearance="@style/TextAppearance.NotificationImportanceButton"
android:text="@string/notification_silence_title"/>
</LinearLayout>
<TextView
android:id="@+id/silence_summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/notification_importance_button_description_top_margin"
android:visibility="gone"
android:text="@string/notification_channel_summary_low"
android:clickable="false"
android:focusable="false"
android:ellipsize="end"
android:maxLines="2"
android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"/>
</com.android.systemui.statusbar.notification.row.ButtonLinearLayout>
</LinearLayout>
<RelativeLayout
android:id="@+id/bottom_buttons"
android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center_vertical"
android:paddingStart="4dp"
android:paddingEnd="4dp"
>
<TextView
android:id="@+id/done"
android:text="@string/inline_ok_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:gravity="end|center_vertical"
android:minWidth="@dimen/notification_importance_toggle_size"
android:minHeight="@dimen/notification_importance_toggle_size"
style="@style/TextAppearance.NotificationInfo.Button"/>
</RelativeLayout>
</LinearLayout>
</com.android.systemui.statusbar.notification.row.NotificationConversationInfo>

View File

@@ -52,8 +52,7 @@
android:layout_centerVertical="true"
android:gravity="center_vertical"
android:layout_alignEnd="@id/pkg_icon"
android:layout_toEndOf="@id/pkg_icon"
android:layout_alignStart="@id/mute">
android:layout_toEndOf="@id/pkg_icon">
<TextView
android:id="@+id/channel_name"
android:layout_width="match_parent"

View File

@@ -1819,6 +1819,18 @@
<!-- [CHAR LIMIT=150] Notification Importance title: bubble level summary -->
<string name="notification_channel_summary_bubble">Keeps your attention with a floating shortcut to this content.</string>
<!-- [CHAR LIMIT=150] Notification Importance title: important conversation level summary -->
<string name="notification_channel_summary_priority">Shows at top of conversation section and appears as a bubble.</string>
<!--[CHAR LIMIT=150] Conversation inline controls footer shown when all conversations from the app are allowed to show as bubbles -->
<string name="notification_conversation_channel_all_bubble">All conversations from <xliff:g id="app_name" example="YouTube">%1$s</xliff:g> bubble by default. Manage in <xliff:g id="app_name" example="Settings">%2$s</xliff:g>.</string>
<!--[CHAR LIMIT=30] Linkable text to Settings app -->
<string name="notification_conversation_channel_settings">Settings</string>
<!-- [CHAR LIMIT=150] Notification Importance title: important conversation level -->
<string name="notification_priority_title">Priority</string>
<!-- [CHAR LIMIT=NONE] Empty overflow title -->
<string name="bubble_overflow_empty_title">No recent bubbles</string>

View File

@@ -20,11 +20,10 @@ import static android.app.Notification.EXTRA_IS_GROUP_CONVERSATION;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_CACHED;
import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC;
import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED;
import static android.provider.Settings.Secure.BUBBLE_IMPORTANT_CONVERSATIONS;
import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.IntDef;
@@ -36,7 +35,6 @@ import android.app.NotificationChannelGroup;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
@@ -49,6 +47,10 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.transition.ChangeBounds;
import android.transition.Fade;
import android.transition.TransitionManager;
import android.transition.TransitionSet;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
@@ -65,13 +67,10 @@ import com.android.settingslib.notification.ConversationIconFactory;
import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.phone.ShadeController;
import java.lang.annotation.Retention;
import java.util.Arrays;
import java.util.List;
/**
@@ -83,11 +82,9 @@ public class NotificationConversationInfo extends LinearLayout implements
private INotificationManager mINotificationManager;
private LauncherApps mLauncherApps;
ShortcutManager mShortcutManager;
private PackageManager mPm;
private VisualStabilityManager mVisualStabilityManager;
private ShadeController mShadeController;
private ConversationIconFactory mIconFactory;
private String mPackageName;
@@ -97,44 +94,34 @@ public class NotificationConversationInfo extends LinearLayout implements
private NotificationChannel mNotificationChannel;
private ShortcutInfo mShortcutInfo;
private String mConversationId;
private NotificationEntry mEntry;
private StatusBarNotification mSbn;
private boolean mIsDeviceProvisioned;
private boolean mStartedAsBubble;
private boolean mIsBubbleable;
private TextView mPriorityDescriptionView;
private TextView mDefaultDescriptionView;
private TextView mSilentDescriptionView;
private @Action int mSelectedAction = -1;
private OnSnoozeClickListener mOnSnoozeClickListener;
private OnSettingsClickListener mOnSettingsClickListener;
private NotificationGuts mGutsContainer;
private BubbleController mBubbleController;
@VisibleForTesting
boolean mSkipPost = false;
@Retention(SOURCE)
@IntDef({ACTION_BUBBLE, ACTION_HOME, ACTION_FAVORITE, ACTION_SNOOZE, ACTION_MUTE,
ACTION_UNBUBBLE, ACTION_SETTINGS})
@IntDef({ACTION_DEFAULT, ACTION_HOME, ACTION_FAVORITE, ACTION_SNOOZE, ACTION_MUTE,
ACTION_SETTINGS})
private @interface Action {}
static final int ACTION_BUBBLE = 0;
static final int ACTION_DEFAULT = 0;
static final int ACTION_HOME = 1;
static final int ACTION_FAVORITE = 2;
static final int ACTION_SNOOZE = 3;
static final int ACTION_MUTE = 4;
static final int ACTION_SETTINGS = 5;
static final int ACTION_UNBUBBLE = 6;
private OnClickListener mOnBubbleClick = v -> {
mSelectedAction = mStartedAsBubble ? ACTION_UNBUBBLE : ACTION_BUBBLE;
if (mStartedAsBubble) {
mBubbleController.onUserDemotedBubbleFromNotification(mEntry);
} else {
mBubbleController.onUserCreatedBubbleFromNotification(mEntry);
}
closeControls(v, true);
};
// TODO: b/152050825
/*
private OnClickListener mOnHomeClick = v -> {
mSelectedAction = ACTION_HOME;
mShortcutManager.requestPinShortcut(mShortcutInfo, null);
@@ -142,21 +129,30 @@ public class NotificationConversationInfo extends LinearLayout implements
closeControls(v, true);
};
private OnClickListener mOnFavoriteClick = v -> {
mSelectedAction = ACTION_FAVORITE;
updateChannel();
};
private OnClickListener mOnSnoozeClick = v -> {
mSelectedAction = ACTION_SNOOZE;
mOnSnoozeClickListener.onClick(v, 1);
closeControls(v, true);
};
*/
private OnClickListener mOnFavoriteClick = v -> {
mSelectedAction = ACTION_FAVORITE;
updateToggleActions(mSelectedAction, true);
};
private OnClickListener mOnDefaultClick = v -> {
mSelectedAction = ACTION_DEFAULT;
updateToggleActions(mSelectedAction, true);
};
private OnClickListener mOnMuteClick = v -> {
mSelectedAction = ACTION_MUTE;
updateChannel();
updateToggleActions(mSelectedAction, true);
};
private OnClickListener mOnDone = v -> {
closeControls(v, true);
};
public NotificationConversationInfo(Context context, AttributeSet attrs) {
@@ -177,7 +173,6 @@ public class NotificationConversationInfo extends LinearLayout implements
public void bindNotification(
ShortcutManager shortcutManager,
LauncherApps launcherApps,
PackageManager pm,
INotificationManager iNotificationManager,
VisualStabilityManager visualStabilityManager,
@@ -185,16 +180,13 @@ public class NotificationConversationInfo extends LinearLayout implements
NotificationChannel notificationChannel,
NotificationEntry entry,
OnSettingsClickListener onSettingsClick,
OnAppSettingsClickListener onAppSettingsClick,
OnSnoozeClickListener onSnoozeClickListener,
ConversationIconFactory conversationIconFactory,
boolean isDeviceProvisioned) {
mSelectedAction = -1;
mINotificationManager = iNotificationManager;
mVisualStabilityManager = visualStabilityManager;
mBubbleController = Dependency.get(BubbleController.class);
mPackageName = pkg;
mEntry = entry;
mSbn = entry.getSbn();
mPm = pm;
mAppName = mPackageName;
@@ -204,11 +196,9 @@ public class NotificationConversationInfo extends LinearLayout implements
mDelegatePkg = mSbn.getOpPkg();
mIsDeviceProvisioned = isDeviceProvisioned;
mOnSnoozeClickListener = onSnoozeClickListener;
mShadeController = Dependency.get(ShadeController.class);
mIconFactory = conversationIconFactory;
mShortcutManager = shortcutManager;
mLauncherApps = launcherApps;
mConversationId = mNotificationChannel.getConversationId();
if (TextUtils.isEmpty(mNotificationChannel.getConversationId())) {
mConversationId = mSbn.getShortcutId(mContext);
@@ -218,16 +208,13 @@ public class NotificationConversationInfo extends LinearLayout implements
}
mShortcutInfo = entry.getRanking().getShortcutInfo();
mIsBubbleable = mEntry.getBubbleMetadata() != null
&& Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.NOTIFICATION_BUBBLES, 0) == 1;
mStartedAsBubble = mEntry.isBubble();
createConversationChannelIfNeeded();
bindHeader();
bindActions();
View done = findViewById(R.id.done);
done.setOnClickListener(mOnDone);
}
void createConversationChannelIfNeeded() {
@@ -252,37 +239,28 @@ public class NotificationConversationInfo extends LinearLayout implements
}
private void bindActions() {
// TODO: figure out what should happen for non-configurable channels
Button bubble = findViewById(R.id.bubble);
bubble.setVisibility(mIsBubbleable ? VISIBLE : GONE);
bubble.setOnClickListener(mOnBubbleClick);
if (mStartedAsBubble) {
bubble.setText(R.string.notification_conversation_unbubble);
} else {
bubble.setText(R.string.notification_conversation_bubble);
}
// TODO: b/152050825
/*
Button home = findViewById(R.id.home);
home.setOnClickListener(mOnHomeClick);
home.setVisibility(mShortcutInfo != null
&& mShortcutManager.isRequestPinShortcutSupported()
? VISIBLE : GONE);
View favorite = findViewById(R.id.fave);
favorite.setOnClickListener(mOnFavoriteClick);
Button snooze = findViewById(R.id.snooze);
snooze.setOnClickListener(mOnSnoozeClick);
*/
View mute = findViewById(R.id.mute);
mute.setOnClickListener(mOnMuteClick);
findViewById(R.id.priority).setOnClickListener(mOnFavoriteClick);
findViewById(R.id.default_behavior).setOnClickListener(mOnDefaultClick);
findViewById(R.id.silence).setOnClickListener(mOnMuteClick);
final View settingsButton = findViewById(R.id.info);
settingsButton.setOnClickListener(getSettingsOnClickListener());
settingsButton.setVisibility(settingsButton.hasOnClickListeners() ? VISIBLE : GONE);
updateToggleActions();
updateToggleActions(getSelectedAction(), false);
}
private void bindHeader() {
@@ -310,16 +288,16 @@ public class NotificationConversationInfo extends LinearLayout implements
// TODO: bring back when channel name does not include name
// bindName();
bindPackage();
bindIcon();
bindIcon(mNotificationChannel.isImportantConversation());
}
private void bindIcon() {
private void bindIcon(boolean important) {
ImageView image = findViewById(R.id.conversation_icon);
if (mShortcutInfo != null) {
image.setImageDrawable(mIconFactory.getConversationDrawable(
mShortcutInfo, mPackageName, mAppUid,
mNotificationChannel.isImportantConversation()));
important));
} else {
if (mSbn.getNotification().extras.getBoolean(EXTRA_IS_GROUP_CONVERSATION, false)) {
// TODO: maybe use a generic group icon, or a composite of recent senders
@@ -378,11 +356,6 @@ public class NotificationConversationInfo extends LinearLayout implements
((TextView) findViewById(R.id.pkg_name)).setText(mAppName);
}
private boolean bubbleImportantConversations() {
return Settings.Secure.getInt(mContext.getContentResolver(),
BUBBLE_IMPORTANT_CONVERSATIONS, 1) == 1;
}
private void bindDelegate() {
TextView delegateView = findViewById(R.id.delegate_name);
@@ -430,6 +403,15 @@ public class NotificationConversationInfo extends LinearLayout implements
}
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mPriorityDescriptionView = findViewById(R.id.priority_summary);
mDefaultDescriptionView = findViewById(R.id.default_summary);
mSilentDescriptionView = findViewById(R.id.silence_summary);
}
@Override
public void onFinishedClosing() {
// TODO: do we need to do anything here?
@@ -450,32 +432,84 @@ public class NotificationConversationInfo extends LinearLayout implements
}
}
private void updateToggleActions() {
ImageButton favorite = findViewById(R.id.fave);
if (mNotificationChannel.isImportantConversation()) {
favorite.setContentDescription(
mContext.getString(R.string.notification_conversation_favorite));
favorite.setImageResource(R.drawable.ic_important);
} else {
favorite.setContentDescription(
mContext.getString(R.string.notification_conversation_unfavorite));
favorite.setImageResource(R.drawable.ic_important_outline);
private void updateToggleActions(int selectedAction, boolean userTriggered) {
if (userTriggered) {
TransitionSet transition = new TransitionSet();
transition.setOrdering(TransitionSet.ORDERING_TOGETHER);
transition.addTransition(new Fade(Fade.OUT))
.addTransition(new ChangeBounds())
.addTransition(
new Fade(Fade.IN)
.setStartDelay(150)
.setDuration(200)
.setInterpolator(FAST_OUT_SLOW_IN));
transition.setDuration(350);
transition.setInterpolator(FAST_OUT_SLOW_IN);
TransitionManager.beginDelayedTransition(this, transition);
}
ImageButton mute = findViewById(R.id.mute);
if (mNotificationChannel.getImportance() >= IMPORTANCE_DEFAULT
|| mNotificationChannel.getImportance() == IMPORTANCE_UNSPECIFIED) {
mute.setContentDescription(
mContext.getString(R.string.notification_conversation_unmute));
mute.setImageResource(R.drawable.ic_notifications_alert);
} else {
mute.setContentDescription(
mContext.getString(R.string.notification_conversation_mute));
mute.setImageResource(R.drawable.ic_notifications_silence);
View priority = findViewById(R.id.priority);
View defaultBehavior = findViewById(R.id.default_behavior);
View silence = findViewById(R.id.silence);
switch (selectedAction) {
case ACTION_FAVORITE:
mPriorityDescriptionView.setVisibility(VISIBLE);
mDefaultDescriptionView.setVisibility(GONE);
mSilentDescriptionView.setVisibility(GONE);
post(() -> {
priority.setSelected(true);
defaultBehavior.setSelected(false);
silence.setSelected(false);
});
break;
case ACTION_MUTE:
mSilentDescriptionView.setVisibility(VISIBLE);
mDefaultDescriptionView.setVisibility(GONE);
mPriorityDescriptionView.setVisibility(GONE);
post(() -> {
priority.setSelected(false);
defaultBehavior.setSelected(false);
silence.setSelected(true);
});
break;
case ACTION_DEFAULT:
mDefaultDescriptionView.setVisibility(VISIBLE);
mSilentDescriptionView.setVisibility(GONE);
mPriorityDescriptionView.setVisibility(GONE);
post(() -> {
priority.setSelected(false);
defaultBehavior.setSelected(true);
silence.setSelected(false);
});
break;
default:
throw new IllegalArgumentException("Unrecognized behavior: " + mSelectedAction);
}
boolean isAChange = getSelectedAction() != selectedAction;
TextView done = findViewById(R.id.done);
done.setText(isAChange
? R.string.inline_ok_button
: R.string.inline_done_button);
// update icon in case importance has changed
bindIcon();
bindIcon(selectedAction == ACTION_FAVORITE);
}
int getSelectedAction() {
if (mNotificationChannel.getImportance() <= IMPORTANCE_LOW
&& mNotificationChannel.getImportance() > IMPORTANCE_UNSPECIFIED) {
return ACTION_MUTE;
} else {
if (mNotificationChannel.isImportantConversation()) {
return ACTION_FAVORITE;
}
}
return ACTION_DEFAULT;
}
private void updateChannel() {
@@ -517,11 +551,7 @@ public class NotificationConversationInfo extends LinearLayout implements
@Override
public boolean shouldBeSaved() {
// Toggle actions are already saved by the time the guts are closed; save for any other
// taps
return mSelectedAction > -1
&& mSelectedAction != ACTION_FAVORITE
&& mSelectedAction != ACTION_MUTE;
return mSelectedAction == ACTION_FAVORITE || mSelectedAction == ACTION_MUTE;
}
@Override
@@ -568,45 +598,41 @@ public class NotificationConversationInfo extends LinearLayout implements
@Override
public void run() {
try {
boolean channelSettingChanged = mAction != ACTION_HOME && mAction != ACTION_SNOOZE;
switch (mAction) {
case ACTION_BUBBLE:
case ACTION_UNBUBBLE:
boolean canBubble = mAction == ACTION_BUBBLE;
if (mChannelToUpdate.canBubble() != canBubble) {
channelSettingChanged = true;
mChannelToUpdate.setAllowBubbles(canBubble);
} else {
channelSettingChanged = false;
}
break;
case ACTION_FAVORITE:
mChannelToUpdate.setImportantConversation(
!mChannelToUpdate.isImportantConversation());
if (mChannelToUpdate.isImportantConversation()
&& bubbleImportantConversations()) {
if (mChannelToUpdate.isImportantConversation()) {
mChannelToUpdate.setAllowBubbles(true);
}
mChannelToUpdate.setImportance(Math.max(
mChannelToUpdate.getOriginalImportance(), IMPORTANCE_DEFAULT));
break;
case ACTION_DEFAULT:
mChannelToUpdate.setImportance(Math.max(
mChannelToUpdate.getOriginalImportance(), IMPORTANCE_DEFAULT));
if (mChannelToUpdate.isImportantConversation()) {
mChannelToUpdate.setImportantConversation(false);
mChannelToUpdate.setAllowBubbles(false);
}
break;
case ACTION_MUTE:
if (mChannelToUpdate.getImportance() == IMPORTANCE_UNSPECIFIED
|| mChannelToUpdate.getImportance() >= IMPORTANCE_DEFAULT) {
mChannelToUpdate.setImportance(IMPORTANCE_LOW);
} else {
mChannelToUpdate.setImportance(Math.max(
mChannelToUpdate.getOriginalImportance(), IMPORTANCE_DEFAULT));
}
if (mChannelToUpdate.isImportantConversation()) {
mChannelToUpdate.setImportantConversation(false);
mChannelToUpdate.setAllowBubbles(false);
}
break;
}
if (channelSettingChanged) {
mINotificationManager.updateNotificationChannelForPackage(
mINotificationManager.updateNotificationChannelForPackage(
mAppPkg, mAppUid, mChannelToUpdate);
}
} catch (RemoteException e) {
Log.e(TAG, "Unable to update notification channel", e);
}
ThreadUtils.postOnMainThread(() -> updateToggleActions());
}
}
}

View File

@@ -394,7 +394,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
notificationInfoView.bindNotification(
mShortcutManager,
mLauncherApps,
pmUser,
mNotificationManager,
mVisualStabilityManager,
@@ -402,7 +401,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
row.getEntry().getChannel(),
row.getEntry(),
onSettingsClick,
onAppSettingsClick,
onSnoozeClickListener,
iconFactoryLoader,
mDeviceProvisionedController.isDeviceProvisioned());

View File

@@ -26,6 +26,8 @@ import static android.provider.Settings.Secure.BUBBLE_IMPORTANT_CONVERSATIONS;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -223,7 +225,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
public void testBindNotification_SetsShortcutIcon() {
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -232,7 +233,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
mIconFactory,
true);
final ImageView view = mNotificationInfo.findViewById(R.id.conversation_icon);
@@ -244,7 +244,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -253,7 +252,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
mIconFactory,
true);
final TextView textView = mNotificationInfo.findViewById(R.id.pkg_name);
@@ -291,7 +289,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -300,7 +297,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
mIconFactory,
true);
final TextView textView = mNotificationInfo.findViewById(R.id.group_name);
@@ -314,7 +310,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
public void testBindNotification_GroupNameHiddenIfNoGroup() {
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -323,7 +318,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
mIconFactory,
true);
final TextView textView = mNotificationInfo.findViewById(R.id.group_name);
@@ -336,7 +330,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
public void testBindNotification_noDelegate() {
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -345,7 +338,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
mIconFactory,
true);
final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
@@ -365,7 +357,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
NotificationEntry entry = new NotificationEntryBuilder().setSbn(mSbn).build();
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -374,7 +365,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
entry,
null,
null,
null,
mIconFactory,
true);
final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
@@ -387,7 +377,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
final CountDownLatch latch = new CountDownLatch(1);
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -399,7 +388,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
latch.countDown();
},
null,
null,
mIconFactory,
true);
@@ -413,7 +401,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() {
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -422,7 +409,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
mIconFactory,
true);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
@@ -434,7 +420,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
final CountDownLatch latch = new CountDownLatch(1);
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -446,7 +431,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
latch.countDown();
},
null,
null,
mIconFactory,
false);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
@@ -454,380 +438,11 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
}
@Test
public void testBindNotification_bubbleActionVisibleWhenCanBubble() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mBubbleEntry,
null,
null,
null,
mIconFactory,
true);
View bubbleView = mNotificationInfo.findViewById(R.id.bubble);
assertEquals(View.VISIBLE, bubbleView.getVisibility());
}
@Test
public void testBindNotification_bubbleAction_noBubbleMetadata() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
null,
null,
null,
mIconFactory,
true);
View bubbleView = mNotificationInfo.findViewById(R.id.bubble);
assertEquals(View.GONE, bubbleView.getVisibility());
}
@Test
public void testBindNotification_bubbleActionGloballyOff() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 0);
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mBubbleEntry,
null,
null,
null,
mIconFactory,
true);
View bubbleView = mNotificationInfo.findViewById(R.id.bubble);
assertEquals(View.GONE, bubbleView.getVisibility());
}
@Test
public void testAddToHome() throws Exception {
when(mShortcutManager.isRequestPinShortcutSupported()).thenReturn(true);
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mBubbleEntry,
null,
null,
null,
mIconFactory,
true);
// Promote it
mNotificationInfo.findViewById(R.id.home).performClick();
mTestableLooper.processAllMessages();
verify(mShortcutManager, times(1)).requestPinShortcut(mShortcutInfo, null);
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), anyInt(), any());
verify(mShadeController).animateCollapsePanels();
}
@Test
public void testSnooze() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mBubbleEntry,
null,
null,
(View v, int hours) -> {
latch.countDown();
},
mIconFactory,
true);
// Promote it
mNotificationInfo.findViewById(R.id.snooze).performClick();
mTestableLooper.processAllMessages();
assertEquals(0, latch.getCount());
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), anyInt(), any());
}
@Test
public void testBubble_promotesBubble() throws Exception {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
mNotificationChannel.setAllowBubbles(false);
mConversationChannel.setAllowBubbles(false);
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mBubbleEntry,
null,
null,
null,
mIconFactory,
true);
assertFalse(mBubbleEntry.isBubble());
// Promote it
mNotificationInfo.findViewById(R.id.bubble).performClick();
mTestableLooper.processAllMessages();
verify(mBubbleController, times(1)).onUserCreatedBubbleFromNotification(mBubbleEntry);
ArgumentCaptor<NotificationChannel> captor =
ArgumentCaptor.forClass(NotificationChannel.class);
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
anyString(), anyInt(), captor.capture());
assertTrue(captor.getValue().canBubble());
}
@Test
public void testBubble_demotesBubble() throws Exception {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
mBubbleEntry.getSbn().getNotification().flags |= FLAG_BUBBLE;
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mBubbleEntry,
null,
null,
null,
mIconFactory,
true);
assertTrue(mBubbleEntry.isBubble());
// Demote it
mNotificationInfo.findViewById(R.id.bubble).performClick();
mTestableLooper.processAllMessages();
verify(mBubbleController, times(1)).onUserDemotedBubbleFromNotification(mBubbleEntry);
ArgumentCaptor<NotificationChannel> captor =
ArgumentCaptor.forClass(NotificationChannel.class);
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
anyString(), anyInt(), captor.capture());
assertFalse(captor.getValue().canBubble());
}
@Test
public void testBubble_noChannelChange() throws Exception {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mBubbleEntry,
null,
null,
null,
mIconFactory,
true);
assertFalse(mBubbleEntry.isBubble());
assertTrue(mNotificationChannel.canBubble());
// Promote it
mNotificationInfo.findViewById(R.id.bubble).performClick();
mTestableLooper.processAllMessages();
verify(mBubbleController, times(1)).onUserCreatedBubbleFromNotification(mBubbleEntry);
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), anyInt(), any());
}
@Test
public void testFavorite_favorite_noBubble() throws Exception {
Settings.Secure.putInt(mContext.getContentResolver(),
BUBBLE_IMPORTANT_CONVERSATIONS, 0);
mNotificationChannel.setAllowBubbles(false);
mConversationChannel.setAllowBubbles(false);
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
null,
null,
null,
mIconFactory,
true);
ImageButton fave = mNotificationInfo.findViewById(R.id.fave);
assertEquals(mContext.getString(R.string.notification_conversation_unfavorite),
fave.getContentDescription().toString());
fave.performClick();
mTestableLooper.processAllMessages();
ArgumentCaptor<NotificationChannel> captor =
ArgumentCaptor.forClass(NotificationChannel.class);
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
anyString(), anyInt(), captor.capture());
assertTrue(captor.getValue().isImportantConversation());
assertFalse(captor.getValue().canBubble());
verify(mBubbleController, never()).onUserCreatedBubbleFromNotification(mEntry);
}
@Test
public void testFavorite_favorite_bubble() throws Exception {
Settings.Secure.putInt(mContext.getContentResolver(),
BUBBLE_IMPORTANT_CONVERSATIONS, 1);
mNotificationChannel.setAllowBubbles(false);
mConversationChannel.setAllowBubbles(false);
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
null,
null,
null,
mIconFactory,
true);
ImageButton fave = mNotificationInfo.findViewById(R.id.fave);
assertEquals(mContext.getString(R.string.notification_conversation_unfavorite),
fave.getContentDescription().toString());
fave.performClick();
mTestableLooper.processAllMessages();
ArgumentCaptor<NotificationChannel> captor =
ArgumentCaptor.forClass(NotificationChannel.class);
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
anyString(), anyInt(), captor.capture());
assertTrue(captor.getValue().isImportantConversation());
assertTrue(captor.getValue().canBubble());
}
@Test
public void testFavorite_unfavorite() throws Exception {
mNotificationChannel.setImportantConversation(true);
mConversationChannel.setImportantConversation(true);
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
null,
null,
null,
mIconFactory,
true);
ImageButton fave = mNotificationInfo.findViewById(R.id.fave);
assertEquals(mContext.getString(R.string.notification_conversation_favorite),
fave.getContentDescription().toString());
fave.performClick();
mTestableLooper.processAllMessages();
ArgumentCaptor<NotificationChannel> captor =
ArgumentCaptor.forClass(NotificationChannel.class);
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
anyString(), anyInt(), captor.capture());
assertFalse(captor.getValue().isImportantConversation());
}
@Test
public void testMute_mute() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mConversationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
null,
null,
null,
mIconFactory,
true);
ImageButton mute = mNotificationInfo.findViewById(R.id.mute);
assertEquals(mContext.getString(R.string.notification_conversation_unmute),
mute.getContentDescription().toString());
mute.performClick();
mTestableLooper.processAllMessages();
ArgumentCaptor<NotificationChannel> captor =
ArgumentCaptor.forClass(NotificationChannel.class);
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
anyString(), anyInt(), captor.capture());
assertEquals(IMPORTANCE_LOW, captor.getValue().getImportance());
}
@Test
public void testMute_unmute() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationChannel.setOriginalImportance(IMPORTANCE_HIGH);
public void testBindNotification_silentSelected_isFave_isSilent() {
mConversationChannel.setImportance(IMPORTANCE_LOW);
mConversationChannel.setOriginalImportance(IMPORTANCE_HIGH);
mConversationChannel.setImportantConversation(true);
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -836,15 +451,200 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
mIconFactory,
true);
View view = mNotificationInfo.findViewById(R.id.silence);
assertThat(view.isSelected()).isTrue();
}
@Test
public void testBindNotification_defaultSelected_notFave_notSilent() {
mConversationChannel.setImportance(IMPORTANCE_HIGH);
mConversationChannel.setImportantConversation(false);
mConversationChannel.setAllowBubbles(true);
mNotificationInfo.bindNotification(
mShortcutManager,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
null,
null,
mIconFactory,
true);
View view = mNotificationInfo.findViewById(R.id.default_behavior);
assertThat(view.isSelected()).isTrue();
}
@Test
public void testFavorite() throws Exception {
mConversationChannel.setAllowBubbles(false);
mConversationChannel.setImportance(IMPORTANCE_LOW);
mConversationChannel.setImportantConversation(false);
mNotificationInfo.bindNotification(
mShortcutManager,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
null,
null,
mIconFactory,
true);
ImageButton mute = mNotificationInfo.findViewById(R.id.mute);
assertEquals(mContext.getString(R.string.notification_conversation_mute),
mute.getContentDescription().toString());
View fave = mNotificationInfo.findViewById(R.id.priority);
fave.performClick();
mTestableLooper.processAllMessages();
mute.performClick();
// silence subtext visible, others not
assertThat(mNotificationInfo.findViewById(R.id.priority_summary).getVisibility())
.isEqualTo(VISIBLE);
assertThat(mNotificationInfo.findViewById(R.id.default_summary).getVisibility())
.isEqualTo(GONE);
assertThat(mNotificationInfo.findViewById(R.id.silence_summary).getVisibility())
.isEqualTo(GONE);
// no changes until hit done
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), anyInt(), any());
assertFalse(mConversationChannel.isImportantConversation());
assertFalse(mConversationChannel.canBubble());
assertEquals(IMPORTANCE_LOW, mConversationChannel.getImportance());
}
@Test
public void testDefault() throws Exception {
mConversationChannel.setAllowBubbles(false);
mConversationChannel.setImportance(IMPORTANCE_LOW);
mConversationChannel.setImportantConversation(false);
mNotificationInfo.bindNotification(
mShortcutManager,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
null,
null,
mIconFactory,
true);
mNotificationInfo.findViewById(R.id.default_behavior).performClick();
mTestableLooper.processAllMessages();
// silence subtext visible, others not
assertThat(mNotificationInfo.findViewById(R.id.priority_summary).getVisibility())
.isEqualTo(GONE);
assertThat(mNotificationInfo.findViewById(R.id.default_summary).getVisibility())
.isEqualTo(VISIBLE);
assertThat(mNotificationInfo.findViewById(R.id.silence_summary).getVisibility())
.isEqualTo(GONE);
// no changes until hit done
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), anyInt(), any());
assertFalse(mConversationChannel.isImportantConversation());
assertFalse(mConversationChannel.canBubble());
assertEquals(IMPORTANCE_LOW, mConversationChannel.getImportance());
}
@Test
public void testSilence() throws Exception {
mConversationChannel.setImportance(IMPORTANCE_DEFAULT);
mConversationChannel.setImportantConversation(false);
mNotificationInfo.bindNotification(
mShortcutManager,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
null,
null,
mIconFactory,
true);
View silence = mNotificationInfo.findViewById(R.id.silence);
silence.performClick();
mTestableLooper.processAllMessages();
// silence subtext visible, others not
assertThat(mNotificationInfo.findViewById(R.id.priority_summary).getVisibility())
.isEqualTo(GONE);
assertThat(mNotificationInfo.findViewById(R.id.default_summary).getVisibility())
.isEqualTo(GONE);
assertThat(mNotificationInfo.findViewById(R.id.silence_summary).getVisibility())
.isEqualTo(VISIBLE);
// no changes until save
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), anyInt(), any());
assertEquals(IMPORTANCE_DEFAULT, mConversationChannel.getImportance());
}
@Test
public void testFavorite_andSave() throws Exception {
mConversationChannel.setAllowBubbles(false);
mConversationChannel.setImportance(IMPORTANCE_LOW);
mConversationChannel.setImportantConversation(false);
mNotificationInfo.bindNotification(
mShortcutManager,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
null,
null,
mIconFactory,
true);
View fave = mNotificationInfo.findViewById(R.id.priority);
fave.performClick();
mNotificationInfo.findViewById(R.id.done).performClick();
mTestableLooper.processAllMessages();
ArgumentCaptor<NotificationChannel> captor =
ArgumentCaptor.forClass(NotificationChannel.class);
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
anyString(), anyInt(), captor.capture());
assertTrue(captor.getValue().isImportantConversation());
assertTrue(captor.getValue().canBubble());
assertEquals(IMPORTANCE_DEFAULT, captor.getValue().getImportance());
}
@Test
public void testFavorite_andSave_doesNotLowerImportance() throws Exception {
mConversationChannel.setOriginalImportance(IMPORTANCE_HIGH);
mConversationChannel.setImportance(9);
mNotificationInfo.bindNotification(
mShortcutManager,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
null,
null,
mIconFactory,
true);
View fave = mNotificationInfo.findViewById(R.id.priority);
fave.performClick();
mNotificationInfo.findViewById(R.id.done).performClick();
mTestableLooper.processAllMessages();
ArgumentCaptor<NotificationChannel> captor =
@@ -855,10 +655,12 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
}
@Test
public void testBindNotification_createsNewChannel() throws Exception {
public void testDefault_andSave() throws Exception {
mConversationChannel.setAllowBubbles(true);
mConversationChannel.setOriginalImportance(IMPORTANCE_HIGH);
mConversationChannel.setImportantConversation(true);
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -867,6 +669,126 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
mIconFactory,
true);
mNotificationInfo.findViewById(R.id.default_behavior).performClick();
mNotificationInfo.findViewById(R.id.done).performClick();
mTestableLooper.processAllMessages();
ArgumentCaptor<NotificationChannel> captor =
ArgumentCaptor.forClass(NotificationChannel.class);
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
anyString(), anyInt(), captor.capture());
assertFalse(captor.getValue().isImportantConversation());
assertFalse(captor.getValue().canBubble());
assertEquals(IMPORTANCE_HIGH, captor.getValue().getImportance());
}
@Test
public void testDefault_andSave_doesNotChangeNonImportantBubbling() throws Exception {
mConversationChannel.setAllowBubbles(true);
mConversationChannel.setOriginalImportance(IMPORTANCE_HIGH);
mConversationChannel.setImportantConversation(false);
mNotificationInfo.bindNotification(
mShortcutManager,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
null,
null,
mIconFactory,
true);
mNotificationInfo.findViewById(R.id.default_behavior).performClick();
mNotificationInfo.findViewById(R.id.done).performClick();
mTestableLooper.processAllMessages();
ArgumentCaptor<NotificationChannel> captor =
ArgumentCaptor.forClass(NotificationChannel.class);
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
anyString(), anyInt(), captor.capture());
assertFalse(captor.getValue().isImportantConversation());
assertTrue(captor.getValue().canBubble());
assertEquals(IMPORTANCE_HIGH, captor.getValue().getImportance());
}
@Test
public void testDefault_andSave_doesNotDemoteImportance() throws Exception {
mConversationChannel.setImportance(9);
mConversationChannel.setOriginalImportance(IMPORTANCE_HIGH);
mNotificationInfo.bindNotification(
mShortcutManager,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
null,
null,
mIconFactory,
true);
mNotificationInfo.findViewById(R.id.default_behavior).performClick();
mNotificationInfo.findViewById(R.id.done).performClick();
mTestableLooper.processAllMessages();
ArgumentCaptor<NotificationChannel> captor =
ArgumentCaptor.forClass(NotificationChannel.class);
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
anyString(), anyInt(), captor.capture());
assertEquals(IMPORTANCE_HIGH, captor.getValue().getImportance());
}
@Test
public void testSilence_andSave() throws Exception {
mConversationChannel.setImportance(IMPORTANCE_DEFAULT);
mConversationChannel.setImportantConversation(true);
mConversationChannel.setAllowBubbles(true);
mNotificationInfo.bindNotification(
mShortcutManager,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
null,
null,
mIconFactory,
true);
View silence = mNotificationInfo.findViewById(R.id.silence);
silence.performClick();
mNotificationInfo.findViewById(R.id.done).performClick();
mTestableLooper.processAllMessages();
ArgumentCaptor<NotificationChannel> captor =
ArgumentCaptor.forClass(NotificationChannel.class);
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
anyString(), anyInt(), captor.capture());
assertFalse(captor.getValue().isImportantConversation());
assertFalse(captor.getValue().canBubble());
assertEquals(IMPORTANCE_LOW, captor.getValue().getImportance());
}
@Test
public void testBindNotification_createsNewChannel() throws Exception {
mNotificationInfo.bindNotification(
mShortcutManager,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mEntry,
null,
null,
mIconFactory,
true);
@@ -880,7 +802,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
mNotificationChannel.setConversationId("", CONVERSATION_ID);
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -889,7 +810,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
mIconFactory,
true);
@@ -903,7 +823,6 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
mConversationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(
mShortcutManager,
mLauncherApps,
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
@@ -912,11 +831,13 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
mIconFactory,
true);
mNotificationInfo.findViewById(R.id.mute).performClick();
mNotificationInfo.findViewById(R.id.silence).performClick();
mNotificationInfo.findViewById(R.id.done).performClick();
mTestableLooper.processAllMessages();
verify(mVisualStabilityManager).temporarilyAllowReordering();
}