Merge "Inline controls redesign" into rvc-dev

This commit is contained in:
TreeHugger Robot
2020-03-06 16:56:42 +00:00
committed by Android (Google) Code Review
7 changed files with 91 additions and 1038 deletions

View File

@@ -121,7 +121,6 @@
android:layout_marginEnd="2dp"
android:ellipsize="end"
android:text="@string/notification_delegate_header"
android:layout_toEndOf="@id/pkg_divider"
android:maxLines="1" />
</LinearLayout>

View File

@@ -27,51 +27,81 @@
android:paddingStart="@*android:dimen/notification_content_margin_start">
<!-- Package Info -->
<RelativeLayout
<LinearLayout
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="@dimen/notification_guts_conversation_header_height"
android:gravity="center_vertical"
android:clipChildren="false"
android:clipToPadding="false">
<ImageView
android:id="@+id/pkgicon"
android:layout_width="@dimen/notification_guts_header_height"
android:layout_height="@dimen/notification_guts_header_height"
android:id="@+id/pkg_icon"
android:layout_width="@dimen/notification_guts_conversation_icon_size"
android:layout_height="@dimen/notification_guts_conversation_icon_size"
android:layout_centerVertical="true"
android:layout_alignParentStart="true"
android:layout_marginEnd="3dp" />
<TextView
android:id="@+id/pkgname"
android:layout_width="wrap_content"
android:layout_marginEnd="15dp" />
<LinearLayout
android:id="@+id/names"
android:layout_weight="1"
android:layout_width="0dp"
android:orientation="vertical"
android:layout_height="wrap_content"
android:minHeight="@dimen/notification_guts_conversation_icon_size"
android:layout_centerVertical="true"
style="@style/TextAppearance.NotificationImportanceHeader"
android:layout_marginStart="3dp"
android:layout_marginEnd="2dp"
android:layout_toEndOf="@id/pkgicon"
android:singleLine="true" />
<TextView
android:id="@+id/pkg_divider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
style="@style/TextAppearance.NotificationImportanceHeader"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
android:layout_toEndOf="@id/pkgname"
android:text="@*android:string/notification_header_divider_symbol" />
<TextView
android:id="@+id/delegate_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
style="@style/TextAppearance.NotificationImportanceHeader"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
android:ellipsize="end"
android:text="@string/notification_delegate_header"
android:layout_toEndOf="@id/pkg_divider"
android:maxLines="1" />
android:gravity="center_vertical"
android:layout_alignEnd="@id/pkg_icon"
android:layout_toEndOf="@id/pkg_icon"
android:layout_alignStart="@id/mute">
<TextView
android:id="@+id/channel_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/TextAppearance.NotificationImportanceChannel"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start"
android:orientation="horizontal">
<TextView
android:id="@+id/pkg_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/TextAppearance.NotificationImportanceChannelGroup"
android:ellipsize="end"
android:maxLines="1"/>
<TextView
android:id="@+id/group_divider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
style="@style/TextAppearance.NotificationImportanceHeader"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
android:text="@*android:string/notification_header_divider_symbol" />
<TextView
android:id="@+id/group_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
style="@style/TextAppearance.NotificationImportanceChannel"/>
</LinearLayout>
<TextView
android:id="@+id/delegate_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
style="@style/TextAppearance.NotificationImportanceHeader"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
android:ellipsize="end"
android:text="@string/notification_delegate_header"
android:maxLines="1" />
</LinearLayout>
<!-- end aligned fields -->
<!-- Optional link to app. Only appears if the channel is not disabled and the app
asked for it -->
<ImageButton
@@ -95,91 +125,6 @@ asked for it -->
android:src="@drawable/ic_settings"
android:layout_alignParentEnd="true"
android:tint="@color/notification_guts_link_icon_tint"/>
</RelativeLayout>
<!-- Channel Info Block -->
<LinearLayout
android:id="@+id/channel_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingEnd="@*android:dimen/notification_content_margin_end"
android:gravity="center"
android:orientation="vertical">
<!-- Channel Name -->
<TextView
android:id="@+id/channel_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
style="@style/TextAppearance.NotificationImportanceChannel"/>
<TextView
android:id="@+id/group_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/TextAppearance.NotificationImportanceChannelGroup"
android:ellipsize="end"
android:maxLines="1"/>
</LinearLayout>
<LinearLayout
android:id="@+id/blocking_helper"
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:paddingEnd="@*android:dimen/notification_content_margin_end"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical">
<!-- blocking helper text. no need for non-configurable check b/c controls won't be
activated in that case -->
<TextView
android:id="@+id/blocking_helper_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="@string/inline_blocking_helper"
style="@*android:style/TextAppearance.DeviceDefault.Notification" />
<RelativeLayout
android:id="@+id/block_buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/notification_guts_button_spacing">
<TextView
android:id="@+id/blocking_helper_turn_off_notifications"
android:text="@string/inline_turn_off_notifications"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_alignParentStart="true"
android:width="110dp"
android:paddingEnd="15dp"
android:breakStrategy="simple"
style="@style/TextAppearance.NotificationInfo.Button"/>
<TextView
android:id="@+id/deliver_silently"
android:text="@string/inline_deliver_silently_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
android:paddingEnd="15dp"
android:width="110dp"
android:breakStrategy="simple"
android:layout_toStartOf="@+id/keep_showing"
style="@style/TextAppearance.NotificationInfo.Button"/>
<TextView
android:id="@+id/keep_showing"
android:text="@string/inline_keep_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
android:width="110dp"
android:breakStrategy="simple"
android:layout_alignParentEnd="true"
style="@style/TextAppearance.NotificationInfo.Button"/>
</RelativeLayout>
</LinearLayout>
@@ -357,34 +302,4 @@ asked for it -->
</RelativeLayout>
</LinearLayout>
<com.android.systemui.statusbar.notification.row.NotificationUndoLayout
android:id="@+id/confirmation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:orientation="horizontal" >
<TextView
android:id="@+id/confirmation_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:layout_marginStart="@*android:dimen/notification_content_margin_start"
android:layout_marginEnd="@*android:dimen/notification_content_margin_start"
android:text="@string/notification_channel_disabled"
style="@style/TextAppearance.NotificationInfo.Confirmation"/>
<TextView
android:id="@+id/undo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="@dimen/notification_importance_toggle_size"
android:minHeight="@dimen/notification_importance_toggle_size"
android:layout_marginTop="@dimen/notification_guts_button_spacing"
android:layout_marginBottom="@dimen/notification_guts_button_spacing"
android:layout_marginStart="@dimen/notification_guts_button_side_margin"
android:layout_marginEnd="@dimen/notification_guts_button_side_margin"
android:layout_gravity="end|center_vertical"
android:text="@string/inline_undo"
style="@style/TextAppearance.NotificationInfo.Button"/>
</com.android.systemui.statusbar.notification.row.NotificationUndoLayout>
</com.android.systemui.statusbar.notification.row.NotificationInfo>

View File

@@ -315,7 +315,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
mNotificationActivityStarter.startNotificationGutsIntent(intent, sbn.getUid(),
row);
};
boolean isForBlockingHelper = row.isBlockingHelperShowing();
if (!userHandle.equals(UserHandle.ALL)
|| mLockscreenUserManager.getCurrentUserId() == UserHandle.USER_SYSTEM) {
@@ -335,13 +334,10 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
row.getEntry().getChannel(),
row.getUniqueChannels(),
row.getEntry(),
mCheckSaveListener,
onSettingsClick,
onAppSettingsClick,
mDeviceProvisionedController.isDeviceProvisioned(),
row.getIsNonblockable(),
isForBlockingHelper,
row.getEntry().getImportance(),
mHighPriorityProvider.isHighPriority(row.getEntry()));
}

View File

@@ -24,10 +24,6 @@ import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.app.INotificationManager;
@@ -53,7 +49,6 @@ import android.transition.TransitionSet;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -63,42 +58,33 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.logging.NotificationCounters;
import java.lang.annotation.Retention;
import java.util.List;
import java.util.Set;
/**
* The guts of a notification revealed when performing a long press. This also houses the blocking
* helper affordance that allows a user to keep/stop notifications after swiping one away.
* The guts of a notification revealed when performing a long press.
*/
public class NotificationInfo extends LinearLayout implements NotificationGuts.GutsContent {
private static final String TAG = "InfoGuts";
@IntDef(prefix = { "ACTION_" }, value = {
ACTION_NONE,
ACTION_UNDO,
ACTION_TOGGLE_ALERT,
ACTION_TOGGLE_SILENT,
ACTION_BLOCK,
})
public @interface NotificationInfoAction {
}
public static final int ACTION_NONE = 0;
static final int ACTION_UNDO = 1;
// standard controls
static final int ACTION_TOGGLE_SILENT = 2;
// unused
static final int ACTION_BLOCK = 3;
// blocking helper
static final int ACTION_DELIVER_SILENTLY = 4;
// standard controls
private static final int ACTION_ALERT = 5;
private static final int ACTION_TOGGLE_ALERT = 5;
private TextView mPriorityDescriptionView;
private TextView mSilentDescriptionView;
@@ -128,101 +114,35 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
@Nullable private Integer mChosenImportance;
private boolean mIsSingleDefaultChannel;
private boolean mIsNonblockable;
private NotificationEntry mEntry;
private StatusBarNotification mSbn;
private AnimatorSet mExpandAnimation;
private boolean mIsDeviceProvisioned;
private CheckSaveListener mCheckSaveListener;
private OnSettingsClickListener mOnSettingsClickListener;
private OnAppSettingsClickListener mAppSettingsClickListener;
private NotificationGuts mGutsContainer;
private Drawable mPkgIcon;
/** Whether this view is being shown as part of the blocking helper. */
private boolean mIsForBlockingHelper;
@VisibleForTesting
boolean mSkipPost = false;
/**
* String that describes how the user exit or quit out of this view, also used as a counter tag.
*/
private String mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
// used by standard ui
private OnClickListener mOnAlert = v -> {
mExitReason = NotificationCounters.BLOCKING_HELPER_KEEP_SHOWING;
mChosenImportance = IMPORTANCE_DEFAULT;
applyAlertingBehavior(BEHAVIOR_ALERTING, true /* userTriggered */);
};
// used by standard ui
private OnClickListener mOnSilent = v -> {
mExitReason = NotificationCounters.BLOCKING_HELPER_DELIVER_SILENTLY;
mChosenImportance = IMPORTANCE_LOW;
applyAlertingBehavior(BEHAVIOR_SILENT, true /* userTriggered */);
};
// used by standard ui
private OnClickListener mOnDismissSettings = v -> {
mPressedApply = true;
closeControls(v, true);
};
// used by blocking helper
private OnClickListener mOnKeepShowing = v -> {
mExitReason = NotificationCounters.BLOCKING_HELPER_KEEP_SHOWING;
closeControls(v, true);
mMetricsLogger.write(getLogMaker().setCategory(
MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
.setType(MetricsEvent.TYPE_ACTION)
.setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_STAY_SILENT));
};
// used by blocking helper
private OnClickListener mOnDeliverSilently = v -> {
handleSaveImportance(
ACTION_DELIVER_SILENTLY, MetricsEvent.BLOCKING_HELPER_CLICK_STAY_SILENT);
};
private void handleSaveImportance(int action, int metricsSubtype) {
Runnable saveImportance = () -> {
saveImportanceAndExitReason(action);
if (mIsForBlockingHelper) {
swapContent(action, true /* animate */);
mMetricsLogger.write(getLogMaker()
.setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
.setType(MetricsEvent.TYPE_ACTION)
.setSubtype(metricsSubtype));
}
};
if (mCheckSaveListener != null) {
mCheckSaveListener.checkSave(saveImportance, mSbn);
} else {
saveImportance.run();
}
}
private OnClickListener mOnUndo = v -> {
// Reset exit counter that we'll log and record an undo event separately (not an exit event)
mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
if (mIsForBlockingHelper) {
logBlockingHelperCounter(NotificationCounters.BLOCKING_HELPER_UNDO);
mMetricsLogger.write(getLogMaker().setCategory(
MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
.setType(MetricsEvent.TYPE_DISMISS)
.setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_UNDO));
} else {
// TODO: this can't happen?
mMetricsLogger.write(importanceChangeLogMaker().setType(MetricsEvent.TYPE_DISMISS));
}
saveImportanceAndExitReason(ACTION_UNDO);
swapContent(ACTION_UNDO, true /* animate */);
};
public NotificationInfo(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -250,30 +170,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
void onClick(View v, Intent intent);
}
@VisibleForTesting
void bindNotification(
final PackageManager pm,
final INotificationManager iNotificationManager,
final VisualStabilityManager visualStabilityManager,
final String pkg,
final NotificationChannel notificationChannel,
final Set<NotificationChannel> uniqueChannelsInRow,
final NotificationEntry entry,
final CheckSaveListener checkSaveListener,
final OnSettingsClickListener onSettingsClick,
final OnAppSettingsClickListener onAppSettingsClick,
boolean isDeviceProvisioned,
boolean isNonblockable,
int importance,
boolean wasShownHighPriority)
throws RemoteException {
bindNotification(pm, iNotificationManager, visualStabilityManager, pkg, notificationChannel,
uniqueChannelsInRow, entry, checkSaveListener, onSettingsClick,
onAppSettingsClick, isDeviceProvisioned, isNonblockable,
false /* isBlockingHelper */,
importance, wasShownHighPriority);
}
public void bindNotification(
PackageManager pm,
INotificationManager iNotificationManager,
@@ -282,13 +178,10 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
NotificationChannel notificationChannel,
Set<NotificationChannel> uniqueChannelsInRow,
NotificationEntry entry,
CheckSaveListener checkSaveListener,
OnSettingsClickListener onSettingsClick,
OnAppSettingsClickListener onAppSettingsClick,
boolean isDeviceProvisioned,
boolean isNonblockable,
boolean isForBlockingHelper,
int importance,
boolean wasShownHighPriority)
throws RemoteException {
mINotificationManager = iNotificationManager;
@@ -298,18 +191,15 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
mPackageName = pkg;
mUniqueChannelsInRow = uniqueChannelsInRow;
mNumUniqueChannelsInRow = uniqueChannelsInRow.size();
mEntry = entry;
mSbn = entry.getSbn();
mPm = pm;
mAppSettingsClickListener = onAppSettingsClick;
mAppName = mPackageName;
mCheckSaveListener = checkSaveListener;
mOnSettingsClickListener = onSettingsClick;
mSingleNotificationChannel = notificationChannel;
mStartingChannelImportance = mSingleNotificationChannel.getImportance();
mWasShownHighPriority = wasShownHighPriority;
mIsNonblockable = isNonblockable;
mIsForBlockingHelper = isForBlockingHelper;
mAppUid = mSbn.getUid();
mDelegatePkg = mSbn.getOpPkg();
mIsDeviceProvisioned = isDeviceProvisioned;
@@ -329,36 +219,12 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
bindHeader();
bindChannelDetails();
if (mIsForBlockingHelper) {
bindBlockingHelper();
} else {
bindInlineControls();
}
bindInlineControls();
mMetricsLogger.write(notificationControlsLogMaker());
}
private void bindBlockingHelper() {
findViewById(R.id.inline_controls).setVisibility(GONE);
findViewById(R.id.blocking_helper).setVisibility(VISIBLE);
findViewById(R.id.undo).setOnClickListener(mOnUndo);
View turnOffButton = findViewById(R.id.blocking_helper_turn_off_notifications);
turnOffButton.setOnClickListener(getSettingsOnClickListener());
turnOffButton.setVisibility(turnOffButton.hasOnClickListeners() ? VISIBLE : GONE);
TextView keepShowing = findViewById(R.id.keep_showing);
keepShowing.setOnClickListener(mOnKeepShowing);
View deliverSilently = findViewById(R.id.deliver_silently);
deliverSilently.setOnClickListener(mOnDeliverSilently);
}
private void bindInlineControls() {
findViewById(R.id.inline_controls).setVisibility(VISIBLE);
findViewById(R.id.blocking_helper).setVisibility(GONE);
if (mIsNonblockable) {
findViewById(R.id.non_configurable_text).setVisibility(VISIBLE);
findViewById(R.id.non_configurable_multichannel_text).setVisibility(GONE);
@@ -414,8 +280,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
// app is gone, just show package name and generic icon
mPkgIcon = mPm.getDefaultActivityIcon();
}
((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(mPkgIcon);
((TextView) findViewById(R.id.pkgname)).setText(mAppName);
((ImageView) findViewById(R.id.pkg_icon)).setImageDrawable(mPkgIcon);
((TextView) findViewById(R.id.pkg_name)).setText(mAppName);
// Delegate
bindDelegate();
@@ -445,8 +311,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
if (mAppUid >= 0 && mOnSettingsClickListener != null && mIsDeviceProvisioned) {
final int appUidF = mAppUid;
return ((View view) -> {
logBlockingHelperCounter(
NotificationCounters.BLOCKING_HELPER_NOTIF_SETTINGS);
mOnSettingsClickListener.onClick(view,
mNumUniqueChannelsInRow > 1 ? null : mSingleNotificationChannel,
appUidF);
@@ -487,16 +351,13 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
private void bindDelegate() {
TextView delegateView = findViewById(R.id.delegate_name);
TextView dividerView = findViewById(R.id.pkg_divider);
CharSequence delegatePkg = null;
if (!TextUtils.equals(mPackageName, mDelegatePkg)) {
// this notification was posted by a delegate!
delegateView.setVisibility(View.VISIBLE);
dividerView.setVisibility(View.VISIBLE);
} else {
delegateView.setVisibility(View.GONE);
dividerView.setVisibility(View.GONE);
}
}
@@ -512,25 +373,19 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
}
}
TextView groupNameView = findViewById(R.id.group_name);
View divider = findViewById(R.id.group_divider);
if (groupName != null) {
groupNameView.setText(groupName);
groupNameView.setVisibility(View.VISIBLE);
groupNameView.setVisibility(VISIBLE);
divider.setVisibility(VISIBLE);
} else {
groupNameView.setVisibility(View.GONE);
}
}
@VisibleForTesting
void logBlockingHelperCounter(String counterTag) {
if (mIsForBlockingHelper) {
mMetricsLogger.count(counterTag, 1);
groupNameView.setVisibility(GONE);
divider.setVisibility(GONE);
}
}
private void saveImportance() {
if (!mIsNonblockable
|| mExitReason != NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS) {
if (!mIsNonblockable) {
if (mChosenImportance == null) {
mChosenImportance = mStartingChannelImportance;
}
@@ -621,99 +476,13 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
: R.string.inline_done_button);
}
private void saveImportanceAndExitReason(@NotificationInfoAction int action) {
switch (action) {
case ACTION_UNDO:
mChosenImportance = mStartingChannelImportance;
break;
case ACTION_DELIVER_SILENTLY:
mExitReason = NotificationCounters.BLOCKING_HELPER_DELIVER_SILENTLY;
mChosenImportance = mWasShownHighPriority
? IMPORTANCE_LOW : mStartingChannelImportance;
break;
default:
throw new IllegalArgumentException();
}
}
// only used for blocking helper
private void swapContent(@NotificationInfoAction int action, boolean animate) {
if (mExpandAnimation != null) {
mExpandAnimation.cancel();
}
View blockingHelper = findViewById(R.id.blocking_helper);
ViewGroup confirmation = findViewById(R.id.confirmation);
TextView confirmationText = findViewById(R.id.confirmation_text);
saveImportanceAndExitReason(action);
switch (action) {
case ACTION_UNDO:
break;
case ACTION_DELIVER_SILENTLY:
confirmationText.setText(R.string.notification_channel_silenced);
break;
default:
throw new IllegalArgumentException();
}
boolean isUndo = action == ACTION_UNDO;
blockingHelper.setVisibility(isUndo ? VISIBLE : GONE);
findViewById(R.id.channel_info).setVisibility(isUndo ? VISIBLE : GONE);
findViewById(R.id.header).setVisibility(isUndo ? VISIBLE : GONE);
confirmation.setVisibility(isUndo ? GONE : VISIBLE);
if (animate) {
ObjectAnimator promptAnim = ObjectAnimator.ofFloat(blockingHelper, View.ALPHA,
blockingHelper.getAlpha(), isUndo ? 1f : 0f);
promptAnim.setInterpolator(isUndo ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
ObjectAnimator confirmAnim = ObjectAnimator.ofFloat(confirmation, View.ALPHA,
confirmation.getAlpha(), isUndo ? 0f : 1f);
confirmAnim.setInterpolator(isUndo ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
mExpandAnimation = new AnimatorSet();
mExpandAnimation.playTogether(promptAnim, confirmAnim);
mExpandAnimation.setDuration(150);
mExpandAnimation.addListener(new AnimatorListenerAdapter() {
boolean mCancelled = false;
@Override
public void onAnimationCancel(Animator animation) {
mCancelled = true;
}
@Override
public void onAnimationEnd(Animator animation) {
if (!mCancelled) {
blockingHelper.setVisibility(isUndo ? VISIBLE : GONE);
confirmation.setVisibility(isUndo ? GONE : VISIBLE);
}
}
});
mExpandAnimation.start();
}
// Since we're swapping/update the content, reset the timeout so the UI can't close
// immediately after the update.
if (mGutsContainer != null) {
mGutsContainer.resetFalsingCheck();
}
}
@Override
public void onFinishedClosing() {
if (mChosenImportance != null) {
mStartingChannelImportance = mChosenImportance;
}
mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
if (mIsForBlockingHelper) {
bindBlockingHelper();
} else {
bindInlineControls();
}
bindInlineControls();
mMetricsLogger.write(notificationControlsLogMaker().setType(MetricsEvent.TYPE_CLOSE));
}
@@ -756,13 +525,10 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
}
/**
* Closes the controls and commits the updated importance values (indirectly). If this view is
* being used to show the blocking helper, this will immediately dismiss the blocking helper and
* commit the updated importance.
* Closes the controls and commits the updated importance values (indirectly).
*
* <p><b>Note,</b> this will only get called once the view is dismissing. This means that the
* user does not have the ability to undo the action anymore. See
* {@link #swapContent(boolean, boolean)} for where undo is handled.
* user does not have the ability to undo the action anymore.
*/
@VisibleForTesting
void closeControls(View v, boolean save) {
@@ -811,7 +577,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
if (save) {
saveImportance();
}
logBlockingHelperCounter(mExitReason);
return false;
}
@@ -822,7 +587,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
@VisibleForTesting
public boolean isAnimating() {
return mExpandAnimation != null && mExpandAnimation.isRunning();
return false;
}
/**
@@ -901,8 +666,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
private LogMaker notificationControlsLogMaker() {
return getLogMaker().setCategory(MetricsEvent.ACTION_NOTE_CONTROLS)
.setType(MetricsEvent.TYPE_OPEN)
.setSubtype(mIsForBlockingHelper ? MetricsEvent.BLOCKING_HELPER_DISPLAY
: MetricsEvent.BLOCKING_HELPER_UNKNOWN);
.setSubtype(MetricsEvent.BLOCKING_HELPER_UNKNOWN);
}
@Retention(SOURCE)

View File

@@ -1,139 +0,0 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.systemui.statusbar.notification.row;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import com.android.systemui.R;
/**
* Custom view for the NotificationInfo confirmation views so that the confirmation text can
* occupy the full width of the notification and push the undo button down to the next line if
* necessary.
*
* @see NotificationInfo
*/
public class NotificationUndoLayout extends FrameLayout {
/**
* View for the prompt/confirmation text to tell the user the previous action was successful.
*/
private View mConfirmationTextView;
/** Undo button (actionable text) view. */
private View mUndoView;
/**
* Whether {@link #mConfirmationTextView} is multiline and will require the full width of the
* parent (which causes the {@link #mUndoView} to push down).
*/
private boolean mIsMultiline = false;
private int mMultilineTopMargin;
public NotificationUndoLayout(Context context) {
this(context, null);
}
public NotificationUndoLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public NotificationUndoLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mConfirmationTextView = findViewById(R.id.confirmation_text);
mUndoView = findViewById(R.id.undo);
mMultilineTopMargin = getResources().getDimensionPixelOffset(
com.android.internal.R.dimen.notification_content_margin_start);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
LayoutParams confirmationLayoutParams =
(LayoutParams) mConfirmationTextView.getLayoutParams();
LayoutParams undoLayoutParams =(LayoutParams) mUndoView.getLayoutParams();
int measuredWidth = getMeasuredWidth();
// Ignore the left margin on the undo button - no need for additional extra space between
// the text and the button.
int requiredWidth = mConfirmationTextView.getMeasuredWidth()
+ confirmationLayoutParams.rightMargin
+ confirmationLayoutParams.leftMargin
+ mUndoView.getMeasuredWidth()
+ undoLayoutParams.rightMargin;
// If the measured width isn't enough to accommodate both the undo button and the text in
// the same line, we'll need to adjust the view to be multi-line. Otherwise, we're done.
if (requiredWidth > measuredWidth) {
mIsMultiline = true;
// Update height requirement to the text height and the button's height (along with
// additional spacing for the top of the text).
int updatedHeight = mMultilineTopMargin
+ mConfirmationTextView.getMeasuredHeight()
+ mUndoView.getMeasuredHeight()
+ undoLayoutParams.topMargin
+ undoLayoutParams.bottomMargin;
setMeasuredDimension(measuredWidth, updatedHeight);
} else {
mIsMultiline = false;
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
// If the text view and undo view don't fit on the same line, we'll need to manually lay
// out the content.
if (mIsMultiline) {
// Re-align parent right/bottom values. Left and top are considered to be 0.
int parentBottom = getMeasuredHeight();
int parentRight = getMeasuredWidth();
LayoutParams confirmationLayoutParams =
(LayoutParams) mConfirmationTextView.getLayoutParams();
LayoutParams undoLayoutParams = (LayoutParams) mUndoView.getLayoutParams();
// The confirmation text occupies the full width as computed earlier. Both side margins
// are equivalent, so we only need to grab the left one here.
mConfirmationTextView.layout(
confirmationLayoutParams.leftMargin,
mMultilineTopMargin,
confirmationLayoutParams.leftMargin + mConfirmationTextView.getMeasuredWidth(),
mMultilineTopMargin + mConfirmationTextView.getMeasuredHeight());
// The undo button is aligned bottom|end with the parent in the case of multiline text.
int undoViewLeft = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL
? undoLayoutParams.rightMargin
: parentRight - mUndoView.getMeasuredWidth() - undoLayoutParams.rightMargin;
mUndoView.layout(
undoViewLeft,
parentBottom - mUndoView.getMeasuredHeight() - undoLayoutParams.bottomMargin,
undoViewLeft + mUndoView.getMeasuredWidth(),
parentBottom - undoLayoutParams.bottomMargin);
} else {
super.onLayout(changed, left, top, right, bottom);
}
}
}

View File

@@ -315,75 +315,10 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.getValue().getAction());
}
@Test
public void testInitializeNotificationInfoView_showBlockingHelper() throws Exception {
NotificationInfo notificationInfoView = mock(NotificationInfo.class);
ExpandableNotificationRow row = spy(mHelper.createRow());
row.setBlockingHelperShowing(true);
modifyRanking(row.getEntry())
.setUserSentiment(USER_SENTIMENT_NEGATIVE)
.build();
when(row.getIsNonblockable()).thenReturn(false);
StatusBarNotification statusBarNotification = row.getEntry().getSbn();
NotificationEntry entry = row.getEntry();
mGutsManager.initializeNotificationInfo(row, notificationInfoView);
verify(notificationInfoView).bindNotification(
any(PackageManager.class),
any(INotificationManager.class),
eq(mVisualStabilityManager),
eq(statusBarNotification.getPackageName()),
any(NotificationChannel.class),
anySet(),
eq(entry),
any(NotificationInfo.CheckSaveListener.class),
any(NotificationInfo.OnSettingsClickListener.class),
any(NotificationInfo.OnAppSettingsClickListener.class),
eq(false),
eq(false),
eq(true) /* isForBlockingHelper */,
eq(0),
eq(false) /* wasShownHighPriority */);
}
@Test
public void testInitializeNotificationInfoView_dontShowBlockingHelper() throws Exception {
NotificationInfo notificationInfoView = mock(NotificationInfo.class);
ExpandableNotificationRow row = spy(mHelper.createRow());
row.setBlockingHelperShowing(false);
modifyRanking(row.getEntry())
.setUserSentiment(USER_SENTIMENT_NEGATIVE)
.build();
when(row.getIsNonblockable()).thenReturn(false);
StatusBarNotification statusBarNotification = row.getEntry().getSbn();
NotificationEntry entry = row.getEntry();
mGutsManager.initializeNotificationInfo(row, notificationInfoView);
verify(notificationInfoView).bindNotification(
any(PackageManager.class),
any(INotificationManager.class),
eq(mVisualStabilityManager),
eq(statusBarNotification.getPackageName()),
any(NotificationChannel.class),
anySet(),
eq(entry),
any(NotificationInfo.CheckSaveListener.class),
any(NotificationInfo.OnSettingsClickListener.class),
any(NotificationInfo.OnAppSettingsClickListener.class),
eq(false),
eq(false),
eq(false) /* isForBlockingHelper */,
eq(0),
eq(false) /* wasShownHighPriority */);
}
@Test
public void testInitializeNotificationInfoView_highPriority() throws Exception {
NotificationInfo notificationInfoView = mock(NotificationInfo.class);
ExpandableNotificationRow row = spy(mHelper.createRow());
row.setBlockingHelperShowing(true);
final NotificationEntry entry = row.getEntry();
modifyRanking(entry)
.setUserSentiment(USER_SENTIMENT_NEGATIVE)
@@ -403,13 +338,10 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
any(NotificationChannel.class),
anySet(),
eq(entry),
any(NotificationInfo.CheckSaveListener.class),
any(NotificationInfo.OnSettingsClickListener.class),
any(NotificationInfo.OnAppSettingsClickListener.class),
eq(false),
eq(false),
eq(true) /* isForBlockingHelper */,
eq(IMPORTANCE_HIGH),
eq(true) /* wasShownHighPriority */);
}
@@ -437,13 +369,10 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
any(NotificationChannel.class),
anySet(),
eq(entry),
any(NotificationInfo.CheckSaveListener.class),
any(NotificationInfo.OnSettingsClickListener.class),
any(NotificationInfo.OnAppSettingsClickListener.class),
eq(true),
eq(false),
eq(false) /* isForBlockingHelper */,
eq(0),
eq(false) /* wasShownHighPriority */);
}
@@ -469,13 +398,10 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
any(NotificationChannel.class),
anySet(),
eq(entry),
any(NotificationInfo.CheckSaveListener.class),
any(NotificationInfo.OnSettingsClickListener.class),
any(NotificationInfo.OnAppSettingsClickListener.class),
eq(false),
eq(false),
eq(true) /* isForBlockingHelper */,
eq(0),
eq(false) /* wasShownHighPriority */);
}

View File

@@ -119,15 +119,10 @@ public class NotificationInfoTest extends SysuiTestCase {
@Mock
private PackageManager mMockPackageManager;
@Mock
private NotificationBlockingHelperManager mBlockingHelperManager;
@Mock
private VisualStabilityManager mVisualStabilityManager;
@Before
public void setUp() throws Exception {
mDependency.injectTestDependency(
NotificationBlockingHelperManager.class,
mBlockingHelperManager);
mTestableLooper = TestableLooper.get(this);
mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
@@ -183,13 +178,6 @@ public class NotificationInfoTest extends SysuiTestCase {
NOTIFICATION_NEW_INTERRUPTION_MODEL, 0);
}
// TODO: if tests are taking too long replace this with something that makes the animation
// finish instantly.
private void waitForUndoButton() {
PollingCheck.waitFor(1000,
() -> VISIBLE == mNotificationInfo.findViewById(R.id.confirmation).getVisibility());
}
@Test
public void testBindNotification_SetsTextApplicationName() throws Exception {
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
@@ -203,12 +191,10 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
final TextView textView = mNotificationInfo.findViewById(R.id.pkgname);
final TextView textView = mNotificationInfo.findViewById(R.id.pkg_name);
assertTrue(textView.getText().toString().contains("App Name"));
assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
}
@@ -228,12 +214,10 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
final ImageView iconView = mNotificationInfo.findViewById(R.id.pkgicon);
final ImageView iconView = mNotificationInfo.findViewById(R.id.pkg_icon);
assertEquals(iconDrawable, iconView.getDrawable());
}
@@ -249,14 +233,12 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
assertEquals(GONE, nameView.getVisibility());
final TextView dividerView = mNotificationInfo.findViewById(R.id.pkg_divider);
final TextView dividerView = mNotificationInfo.findViewById(R.id.group_divider);
assertEquals(GONE, dividerView.getVisibility());
}
@@ -281,16 +263,12 @@ public class NotificationInfoTest extends SysuiTestCase {
entry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
assertEquals(VISIBLE, nameView.getVisibility());
assertTrue(nameView.getText().toString().contains("Proxied"));
final TextView dividerView = mNotificationInfo.findViewById(R.id.pkg_divider);
assertEquals(VISIBLE, dividerView.getVisibility());
}
@Test
@@ -305,13 +283,13 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
assertEquals(GONE, groupNameView.getVisibility());
final TextView dividerView = mNotificationInfo.findViewById(R.id.group_divider);
assertEquals(GONE, dividerView.getVisibility());
}
@Test
@@ -332,14 +310,14 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
assertEquals(View.VISIBLE, groupNameView.getVisibility());
assertEquals("Test Group Name", groupNameView.getText());
final TextView dividerView = mNotificationInfo.findViewById(R.id.group_divider);
assertEquals(View.VISIBLE, dividerView.getVisibility());
}
@Test
@@ -354,10 +332,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(TEST_CHANNEL_NAME, textView.getText());
@@ -375,10 +351,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(GONE, textView.getVisibility());
@@ -387,7 +361,7 @@ public class NotificationInfoTest extends SysuiTestCase {
@Test
public void testBindNotification_DefaultChannelUsesChannelNameIfMoreChannelsExist()
throws Exception {
// Package has one channel by default.
// Package has more than one channel by default.
when(mMockINotificationManager.getNumNotificationChannelsForPackage(
eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(10);
mNotificationInfo.bindNotification(
@@ -400,10 +374,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(VISIBLE, textView.getVisibility());
@@ -421,41 +393,13 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
true,
IMPORTANCE_DEFAULT,
true);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(VISIBLE, textView.getVisibility());
}
@Test
public void testBindNotification_BlockLink_BlockingHelper() throws Exception {
mNotificationInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
mEntry,
null,
mock(NotificationInfo.OnSettingsClickListener.class),
null,
true,
false,
true /* isBlockingHelper */,
IMPORTANCE_DEFAULT,
true);
final View block =
mNotificationInfo.findViewById(R.id.blocking_helper_turn_off_notifications);
final View interruptivenessSettings = mNotificationInfo.findViewById(
R.id.inline_controls);
assertEquals(VISIBLE, block.getVisibility());
assertEquals(GONE, interruptivenessSettings.getVisibility());
}
@Test
public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
@@ -467,7 +411,6 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel,
mNotificationChannelSet,
mEntry,
null,
(View v, NotificationChannel c, int appUid) -> {
assertEquals(mNotificationChannel, c);
latch.countDown();
@@ -475,7 +418,6 @@ public class NotificationInfoTest extends SysuiTestCase {
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
@@ -496,10 +438,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertTrue(settingsButton.getVisibility() != View.VISIBLE);
@@ -516,14 +456,12 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel,
mNotificationChannelSet,
mEntry,
null,
(View v, NotificationChannel c, int appUid) -> {
assertEquals(mNotificationChannel, c);
},
null,
false,
false,
IMPORTANCE_DEFAULT,
true);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertTrue(settingsButton.getVisibility() != View.VISIBLE);
@@ -541,10 +479,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
mNotificationInfo.bindNotification(
mMockPackageManager,
@@ -554,88 +490,15 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel,
mNotificationChannelSet,
mEntry,
null,
(View v, NotificationChannel c, int appUid) -> { },
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertEquals(View.VISIBLE, settingsButton.getVisibility());
}
@Test
public void testBindNotificationLogging_notBlockingHelper() throws Exception {
mNotificationInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
verify(mMetricsLogger).write(argThat(logMaker ->
logMaker.getCategory() == MetricsEvent.ACTION_NOTE_CONTROLS
&& logMaker.getType() == MetricsEvent.TYPE_OPEN
&& logMaker.getSubtype() == MetricsEvent.BLOCKING_HELPER_UNKNOWN
));
}
@Test
public void testBindNotificationLogging_BlockingHelper() throws Exception {
mNotificationInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
mEntry,
null,
null,
null,
false,
true,
true,
IMPORTANCE_DEFAULT,
true);
verify(mMetricsLogger).write(argThat(logMaker ->
logMaker.getCategory() == MetricsEvent.ACTION_NOTE_CONTROLS
&& logMaker.getType() == MetricsEvent.TYPE_OPEN
&& logMaker.getSubtype() == MetricsEvent.BLOCKING_HELPER_DISPLAY
));
}
@Test
public void testLogBlockingHelperCounter_logsForBlockingHelper() throws Exception {
mNotificationInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
mEntry,
null,
null,
null,
false,
true,
true,
IMPORTANCE_DEFAULT,
true);
mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
verify(mMetricsLogger).count(eq("HowCanNotifsBeRealIfAppsArent"), eq(1));
}
@Test
public void testOnClickListenerPassesNullChannelForBundle() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
@@ -646,7 +509,6 @@ public class NotificationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME, mNotificationChannel,
createMultipleChannelSet(MULTIPLE_CHANNEL_COUNT),
mEntry,
null,
(View v, NotificationChannel c, int appUid) -> {
assertEquals(null, c);
latch.countDown();
@@ -654,7 +516,6 @@ public class NotificationInfoTest extends SysuiTestCase {
null,
true,
true,
IMPORTANCE_DEFAULT,
true);
mNotificationInfo.findViewById(R.id.info).performClick();
@@ -676,10 +537,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
final TextView channelNameView =
mNotificationInfo.findViewById(R.id.channel_name);
@@ -699,10 +558,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
assertEquals(GONE, mNotificationInfo.findViewById(
R.id.interruptiveness_settings).getVisibility());
@@ -722,10 +579,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
true,
IMPORTANCE_DEFAULT,
true);
final TextView view = mNotificationInfo.findViewById(R.id.non_configurable_text);
assertEquals(View.VISIBLE, view.getVisibility());
@@ -747,10 +602,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
assertTrue(mNotificationInfo.findViewById(R.id.alert).isSelected());
}
@@ -767,10 +620,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
false);
assertTrue(mNotificationInfo.findViewById(R.id.silence).isSelected());
}
@@ -787,10 +638,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
mTestableLooper.processAllMessages();
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
@@ -810,10 +659,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_LOW,
false);
mNotificationInfo.findViewById(R.id.alert).performClick();
@@ -836,10 +683,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
mNotificationInfo.findViewById(R.id.silence).performClick();
@@ -862,10 +707,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
mNotificationInfo.handleCloseControls(true, false);
@@ -889,10 +732,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_UNSPECIFIED,
true);
mNotificationInfo.handleCloseControls(true, false);
@@ -903,225 +744,6 @@ public class NotificationInfoTest extends SysuiTestCase {
assertEquals(IMPORTANCE_UNSPECIFIED, mNotificationChannel.getImportance());
}
@Test
public void testCloseControls_nonNullCheckSaveListenerDoesntDelayKeepShowing_BlockingHelper()
throws Exception {
NotificationInfo.CheckSaveListener listener =
mock(NotificationInfo.CheckSaveListener.class);
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel /* notificationChannel */,
createMultipleChannelSet(10) /* numUniqueChannelsInRow */,
mEntry,
listener /* checkSaveListener */,
null /* onSettingsClick */,
null /* onAppSettingsClick */,
true /* provisioned */,
false /* isNonblockable */,
true /* isForBlockingHelper */,
IMPORTANCE_DEFAULT,
true);
NotificationGuts guts = spy(new NotificationGuts(mContext, null));
when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
doNothing().when(guts).animateClose(anyInt(), anyInt(), anyBoolean());
doNothing().when(guts).setExposed(anyBoolean(), anyBoolean());
guts.setGutsContent(mNotificationInfo);
mNotificationInfo.setGutsParent(guts);
mNotificationInfo.findViewById(R.id.keep_showing).performClick();
verify(mBlockingHelperManager).dismissCurrentBlockingHelper();
mTestableLooper.processAllMessages();
verify(mMockINotificationManager, times(1))
.setNotificationsEnabledWithImportanceLockForPackage(
anyString(), eq(TEST_UID), eq(true));
}
@Test
public void testCloseControls_nonNullCheckSaveListenerDoesntDelayDismiss_BlockingHelper()
throws Exception {
NotificationInfo.CheckSaveListener listener =
mock(NotificationInfo.CheckSaveListener.class);
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel /* notificationChannel */,
createMultipleChannelSet(10) /* numUniqueChannelsInRow */,
mEntry,
listener /* checkSaveListener */,
null /* onSettingsClick */,
null /* onAppSettingsClick */,
false /* isNonblockable */,
true /* isForBlockingHelper */,
true, IMPORTANCE_DEFAULT,
true);
mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
mTestableLooper.processAllMessages();
verify(listener, times(0)).checkSave(any(Runnable.class), eq(mSbn));
}
@Test
public void testCloseControls_checkSaveListenerDelaysStopNotifications_BlockingHelper()
throws Exception {
NotificationInfo.CheckSaveListener listener =
mock(NotificationInfo.CheckSaveListener.class);
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel /* notificationChannel */,
createMultipleChannelSet(10) /* numUniqueChannelsInRow */,
mEntry,
listener /* checkSaveListener */,
null /* onSettingsClick */,
null /* onAppSettingsClick */,
true /* provisioned */,
false /* isNonblockable */,
true /* isForBlockingHelper */,
IMPORTANCE_DEFAULT,
true);
mNotificationInfo.findViewById(R.id.deliver_silently).performClick();
mTestableLooper.processAllMessages();
verify(listener).checkSave(any(Runnable.class), eq(mSbn));
}
@Test
public void testCloseControls_blockingHelperDismissedIfShown() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet /* numChannels */,
mEntry,
null /* checkSaveListener */,
null /* onSettingsClick */,
null /* onAppSettingsClick */,
false /* isNonblockable */,
true /* isForBlockingHelper */,
true,
IMPORTANCE_DEFAULT,
true);
NotificationGuts guts = mock(NotificationGuts.class);
doCallRealMethod().when(guts).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
mNotificationInfo.setGutsParent(guts);
mNotificationInfo.closeControls(mNotificationInfo, true);
verify(mBlockingHelperManager).dismissCurrentBlockingHelper();
}
@Test
public void testSilentlyChangedCallsUpdateNotificationChannel_blockingHelper()
throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet /* numChannels */,
mEntry,
null /* checkSaveListener */,
null /* onSettingsClick */,
null /* onAppSettingsClick */,
true /*provisioned */,
false /* isNonblockable */,
true /* isForBlockingHelper */,
IMPORTANCE_DEFAULT,
true);
mNotificationInfo.findViewById(R.id.deliver_silently).performClick();
waitForUndoButton();
mNotificationInfo.handleCloseControls(true, false);
mTestableLooper.processAllMessages();
ArgumentCaptor<NotificationChannel> updated =
ArgumentCaptor.forClass(NotificationChannel.class);
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
anyString(), eq(TEST_UID), updated.capture());
assertTrue((updated.getValue().getUserLockedFields()
& USER_LOCKED_IMPORTANCE) != 0);
assertEquals(IMPORTANCE_LOW, updated.getValue().getImportance());
}
@Test
public void testKeepUpdatesNotificationChannel_blockingHelper() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
mEntry,
null,
null,
null,
true,
true,
IMPORTANCE_LOW,
false);
mNotificationInfo.findViewById(R.id.keep_showing).performClick();
mNotificationInfo.handleCloseControls(true, false);
mTestableLooper.processAllMessages();
ArgumentCaptor<NotificationChannel> updated =
ArgumentCaptor.forClass(NotificationChannel.class);
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
anyString(), eq(TEST_UID), updated.capture());
assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
}
@Test
public void testNoActionsUpdatesNotificationChannel_blockingHelper() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
mVisualStabilityManager,
TEST_PACKAGE_NAME,
mNotificationChannel,
mNotificationChannelSet,
mEntry,
null,
null,
null,
true,
true,
IMPORTANCE_DEFAULT,
true);
mNotificationInfo.handleCloseControls(true, false);
mTestableLooper.processAllMessages();
ArgumentCaptor<NotificationChannel> updated =
ArgumentCaptor.forClass(NotificationChannel.class);
verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
anyString(), eq(TEST_UID), updated.capture());
assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
assertEquals(IMPORTANCE_DEFAULT, mNotificationChannel.getImportance());
}
@Test
public void testSilenceCallsUpdateNotificationChannel() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
@@ -1135,10 +757,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
mNotificationInfo.findViewById(R.id.silence).performClick();
@@ -1168,10 +788,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_LOW,
false);
mNotificationInfo.findViewById(R.id.alert).performClick();
@@ -1202,10 +820,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_UNSPECIFIED,
true);
mNotificationInfo.findViewById(R.id.silence).performClick();
@@ -1236,10 +852,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_MIN,
false);
assertEquals(mContext.getString(R.string.inline_done_button),
@@ -1273,10 +887,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_MIN,
false);
assertEquals(mContext.getString(R.string.inline_done_button),
@@ -1309,10 +921,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_DEFAULT,
true);
mNotificationInfo.findViewById(R.id.silence).performClick();
@@ -1336,10 +946,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_LOW,
false);
assertEquals(mContext.getString(R.string.inline_done_button),
@@ -1366,10 +974,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_LOW,
false);
mNotificationInfo.findViewById(R.id.alert).performClick();
@@ -1399,10 +1005,8 @@ public class NotificationInfoTest extends SysuiTestCase {
mEntry,
null,
null,
null,
true,
false,
IMPORTANCE_LOW,
false);
mNotificationInfo.findViewById(R.id.alert).performClick();
@@ -1425,14 +1029,10 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel,
mNotificationChannelSet,
mEntry,
(Runnable saveImportance, StatusBarNotification sbn) -> {
saveImportance.run();
},
null,
null,
true,
false,
IMPORTANCE_LOW,
false
);
@@ -1460,14 +1060,10 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel,
mNotificationChannelSet,
mEntry,
(Runnable saveImportance, StatusBarNotification sbn) -> {
saveImportance.run();
},
null,
null,
true,
false,
IMPORTANCE_LOW,
false
);
@@ -1488,14 +1084,10 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel,
mNotificationChannelSet,
mEntry,
(Runnable saveImportance, StatusBarNotification sbn) -> {
saveImportance.run();
},
null,
null,
true,
false,
IMPORTANCE_LOW,
false
);