Merge "Merge "DexLoadReporter needs to handle arbitrary class loaders." am: f2d5ace011 am: 1e29264790 am: 0a0559c0ce"
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 56e6aea..64eae0c 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -1462,6 +1462,7 @@
private @UserSentiment int mUserSentiment = USER_SENTIMENT_NEUTRAL;
private boolean mHidden;
private boolean mAudiblyAlerted;
+ private boolean mNoisy;
private ArrayList<Notification.Action> mSmartActions;
private ArrayList<CharSequence> mSmartReplies;
@@ -1636,6 +1637,11 @@
return mAudiblyAlerted;
}
+ /** @hide */
+ public boolean isNoisy() {
+ return mNoisy;
+ }
+
/**
* @hide
*/
@@ -1646,7 +1652,8 @@
NotificationChannel channel, ArrayList<String> overridePeople,
ArrayList<SnoozeCriterion> snoozeCriteria, boolean showBadge,
int userSentiment, boolean hidden, boolean audiblyAlerted,
- ArrayList<Notification.Action> smartActions, ArrayList<CharSequence> smartReplies) {
+ boolean noisy, ArrayList<Notification.Action> smartActions,
+ ArrayList<CharSequence> smartReplies) {
mKey = key;
mRank = rank;
mIsAmbient = importance < NotificationManager.IMPORTANCE_LOW;
@@ -1663,6 +1670,7 @@
mUserSentiment = userSentiment;
mHidden = hidden;
mAudiblyAlerted = audiblyAlerted;
+ mNoisy = noisy;
mSmartActions = smartActions;
mSmartReplies = smartReplies;
}
@@ -1715,6 +1723,7 @@
private ArrayMap<String, Integer> mUserSentiment;
private ArrayMap<String, Boolean> mHidden;
private ArrayMap<String, Boolean> mAudiblyAlerted;
+ private ArrayMap<String, Boolean> mNoisy;
private ArrayMap<String, ArrayList<Notification.Action>> mSmartActions;
private ArrayMap<String, ArrayList<CharSequence>> mSmartReplies;
@@ -1746,7 +1755,8 @@
getImportance(key), getImportanceExplanation(key), getOverrideGroupKey(key),
getChannel(key), getOverridePeople(key), getSnoozeCriteria(key),
getShowBadge(key), getUserSentiment(key), getHidden(key),
- getAudiblyAlerted(key), getSmartActions(key), getSmartReplies(key));
+ getAudiblyAlerted(key), getNoisy(key), getSmartActions(key),
+ getSmartReplies(key));
return rank >= 0;
}
@@ -1894,6 +1904,16 @@
return audiblyAlerted == null ? false : audiblyAlerted.booleanValue();
}
+ private boolean getNoisy(String key) {
+ synchronized (this) {
+ if (mNoisy == null) {
+ buildNoisyLocked();
+ }
+ }
+ Boolean noisy = mNoisy.get(key);
+ return noisy == null ? false : noisy.booleanValue();
+ }
+
private ArrayList<Notification.Action> getSmartActions(String key) {
synchronized (this) {
if (mSmartActions == null) {
@@ -2034,6 +2054,11 @@
}
// Locked by 'this'
+ private void buildNoisyLocked() {
+ mNoisy = buildBooleanMapFromBundle(mRankingUpdate.getNoisy());
+ }
+
+ // Locked by 'this'
private void buildSmartActions() {
Bundle smartActions = mRankingUpdate.getSmartActions();
mSmartActions = new ArrayMap<>(smartActions.size());
diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java
index b561bfd..f80df93 100644
--- a/core/java/android/service/notification/NotificationRankingUpdate.java
+++ b/core/java/android/service/notification/NotificationRankingUpdate.java
@@ -40,13 +40,14 @@
private final Bundle mSmartActions;
private final Bundle mSmartReplies;
private final Bundle mAudiblyAlerted;
+ private final Bundle mNoisy;
public NotificationRankingUpdate(String[] keys, String[] interceptedKeys,
Bundle visibilityOverrides, Bundle suppressedVisualEffects,
int[] importance, Bundle explanation, Bundle overrideGroupKeys,
Bundle channels, Bundle overridePeople, Bundle snoozeCriteria,
Bundle showBadge, Bundle userSentiment, Bundle hidden, Bundle smartActions,
- Bundle smartReplies, Bundle audiblyAlerted) {
+ Bundle smartReplies, Bundle audiblyAlerted, Bundle noisy) {
mKeys = keys;
mInterceptedKeys = interceptedKeys;
mVisibilityOverrides = visibilityOverrides;
@@ -63,6 +64,7 @@
mSmartActions = smartActions;
mSmartReplies = smartReplies;
mAudiblyAlerted = audiblyAlerted;
+ mNoisy = noisy;
}
public NotificationRankingUpdate(Parcel in) {
@@ -83,6 +85,7 @@
mSmartActions = in.readBundle();
mSmartReplies = in.readBundle();
mAudiblyAlerted = in.readBundle();
+ mNoisy = in.readBundle();
}
@Override
@@ -108,6 +111,7 @@
out.writeBundle(mSmartActions);
out.writeBundle(mSmartReplies);
out.writeBundle(mAudiblyAlerted);
+ out.writeBundle(mNoisy);
}
public static final Parcelable.Creator<NotificationRankingUpdate> CREATOR
@@ -184,4 +188,8 @@
public Bundle getAudiblyAlerted() {
return mAudiblyAlerted;
}
+
+ public Bundle getNoisy() {
+ return mNoisy;
+ }
}
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index f138685..c86ebe7 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -152,6 +152,13 @@
android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
style="@style/TextAppearance.NotificationInfo.Button" />
<TextView
+ android:id="@+id/toggle_silent"
+ android:text="@string/inline_silent_button_silent"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
+ style="@style/TextAppearance.NotificationInfo.Button" />
+ <TextView
android:id="@+id/keep"
android:minWidth="48dp"
android:text="@string/inline_keep_button"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 6f5d657..50454fc 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1540,6 +1540,12 @@
<!-- Notification inline controls: Shown when a channel's notifications are minimized -->
<string name="notification_channel_minimized">These notifications will be minimized</string>
+ <!-- Notification inline controls: Shown when a channel's notifications are silenced [CHAR_LIMIT=100] -->
+ <string name="notification_channel_silenced">These notifications will be shown silently</string>
+
+ <!-- Notification inline controls: Shown when a channel's notifications are set to alert [CHAR_LIMIT=100] -->
+ <string name="notification_channel_unsilenced">These notifications will alert you</string>
+
<!-- Notification Inline controls: continue receiving notifications prompt, channel level -->
<string name="inline_blocking_helper">You usually dismiss these notifications.
\nKeep showing them?</string>
@@ -1556,6 +1562,12 @@
<!-- Notification inline controls: minimize notifications button -->
<string name="inline_minimize_button">Minimize</string>
+ <!-- Notification inline controls: show notifications silently button [CHAR_LIMIT=25] -->
+ <string name="inline_silent_button_silent">Show silently</string>
+
+ <!-- Notification inline controls: show and alert button [CHAR_LIMIT=25] -->
+ <string name="inline_silent_button_alert">Show and alert</string>
+
<!-- Notification Inline controls: continue receiving notifications prompt, app level -->
<string name="inline_keep_showing_app">Keep showing notifications from this app?</string>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
index b84b77c..f7c07f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
@@ -102,6 +102,8 @@
public StatusBarNotification notification;
public NotificationChannel channel;
public boolean audiblyAlerted;
+ public boolean noisy;
+ public int importance;
public StatusBarIconView icon;
public StatusBarIconView expandedIcon;
public ExpandableNotificationRow row; // the outer expanded view
@@ -155,6 +157,8 @@
public void populateFromRanking(@NonNull Ranking ranking) {
channel = ranking.getChannel();
audiblyAlerted = ranking.audiblyAlerted();
+ noisy = ranking.isNoisy();
+ importance = ranking.getImportance();
snoozeCriteria = ranking.getSnoozeCriteria();
userSentiment = ranking.getUserSentiment();
smartActions = ranking.getSmartActions() == null
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java
index 28c07a3..43b5503 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java
@@ -30,6 +30,9 @@
/** Counter tag for when the user hits 'stop notifications' in the blocking helper. */
public static final String BLOCKING_HELPER_STOP_NOTIFICATIONS =
"blocking_helper_stop_notifications";
+ /** Counter tag for when the user hits 'show silently' in the blocking helper. */
+ public static final String BLOCKING_HELPER_TOGGLE_SILENT =
+ "blocking_helper_toggle_silent";
/** Counter tag for when the user hits 'keep showing' in the blocking helper. */
public static final String BLOCKING_HELPER_KEEP_SHOWING =
"blocking_helper_keep_showing";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
index 0a197da..fbe9c5d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
@@ -23,7 +23,6 @@
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Handler;
-import androidx.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@@ -31,6 +30,8 @@
import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
+import androidx.annotation.Nullable;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
@@ -98,6 +99,11 @@
* Return whether something changed and needs to be saved, possibly requiring a bouncer.
*/
boolean shouldBeSaved();
+
+ /**
+ * Called when the guts view has finished its close animation.
+ */
+ default void onFinishedClosing() {}
}
public interface OnGutsClosedListener {
@@ -304,7 +310,7 @@
x, y, r, 0);
a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
- a.addListener(new AnimateCloseListener(this /* view */));
+ a.addListener(new AnimateCloseListener(this /* view */, mGutsContent));
a.start();
} else {
// Fade in the blocking helper.
@@ -312,11 +318,12 @@
.alpha(0f)
.setDuration(StackStateAnimator.ANIMATION_DURATION_BLOCKING_HELPER_FADE)
.setInterpolator(Interpolators.ALPHA_OUT)
- .setListener(new AnimateCloseListener(this /* view */))
+ .setListener(new AnimateCloseListener(this, /* view */mGutsContent))
.start();
}
} else {
Log.w(TAG, "Failed to animate guts close");
+ mGutsContent.onFinishedClosing();
}
}
@@ -414,15 +421,18 @@
/** Listener for animations executed in {@link #animateClose(int, int, boolean)}. */
private static class AnimateCloseListener extends AnimatorListenerAdapter {
final View mView;
+ private final GutsContent mGutsContent;
- private AnimateCloseListener(View view) {
+ private AnimateCloseListener(View view, GutsContent gutsContent) {
mView = view;
+ mGutsContent = gutsContent;
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mView.setVisibility(View.GONE);
+ mGutsContent.onFinishedClosing();
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 2499952..b838c9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -28,7 +28,6 @@
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.Uri;
-import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
@@ -46,15 +45,13 @@
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -298,7 +295,9 @@
mDeviceProvisionedController.isDeviceProvisioned(),
row.getIsNonblockable(),
isForBlockingHelper,
- row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE);
+ row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE,
+ row.getEntry().noisy,
+ row.getEntry().importance);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index 903c272..522da4d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -16,13 +16,18 @@
package com.android.systemui.statusbar.notification.row;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
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;
import android.app.Notification;
@@ -54,6 +59,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.logging.NotificationCounters;
import java.util.List;
@@ -65,6 +71,17 @@
public class NotificationInfo extends LinearLayout implements NotificationGuts.GutsContent {
private static final String TAG = "InfoGuts";
+ @IntDef(prefix = { "SWAP_CONTENT_" }, value = {
+ SWAP_CONTENT_UNDO,
+ SWAP_CONTENT_TOGGLE_SILENT,
+ SWAP_CONTENT_BLOCK,
+ })
+ @interface SwapContentAction {}
+
+ private static final int SWAP_CONTENT_UNDO = 0;
+ private static final int SWAP_CONTENT_TOGGLE_SILENT = 1;
+ private static final int SWAP_CONTENT_BLOCK = 2;
+
private INotificationManager mINotificationManager;
private PackageManager mPm;
private MetricsLogger mMetricsLogger;
@@ -74,7 +91,8 @@
private int mAppUid;
private int mNumUniqueChannelsInRow;
private NotificationChannel mSingleNotificationChannel;
- private int mStartingUserImportance;
+ private int mStartingChannelImportance;
+ private int mStartingChannelOrNotificationImportance;
private int mChosenImportance;
private boolean mIsSingleDefaultChannel;
private boolean mIsNonblockable;
@@ -82,6 +100,7 @@
private AnimatorSet mExpandAnimation;
private boolean mIsForeground;
private boolean mIsDeviceProvisioned;
+ private boolean mIsNoisy;
private CheckSaveListener mCheckSaveListener;
private OnSettingsClickListener mOnSettingsClickListener;
@@ -102,10 +121,22 @@
closeControls(v);
};
+ private OnClickListener mOnToggleSilent = v -> {
+ Runnable saveImportance = () -> {
+ mExitReason = NotificationCounters.BLOCKING_HELPER_TOGGLE_SILENT;
+ swapContent(SWAP_CONTENT_TOGGLE_SILENT);
+ };
+ if (mCheckSaveListener != null) {
+ mCheckSaveListener.checkSave(saveImportance, mSbn);
+ } else {
+ saveImportance.run();
+ }
+ };
+
private OnClickListener mOnStopOrMinimizeNotifications = v -> {
Runnable saveImportance = () -> {
mExitReason = NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS;
- swapContent(false);
+ swapContent(SWAP_CONTENT_BLOCK);
};
if (mCheckSaveListener != null) {
mCheckSaveListener.checkSave(saveImportance, mSbn);
@@ -118,7 +149,7 @@
// Reset exit counter that we'll log and record an undo event separately (not an exit event)
mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
logBlockingHelperCounter(NotificationCounters.BLOCKING_HELPER_UNDO);
- swapContent(true);
+ swapContent(SWAP_CONTENT_UNDO);
};
public NotificationInfo(Context context, AttributeSet attrs) {
@@ -152,12 +183,15 @@
final OnSettingsClickListener onSettingsClick,
final OnAppSettingsClickListener onAppSettingsClick,
boolean isDeviceProvisioned,
- boolean isNonblockable)
+ boolean isNonblockable,
+ boolean isNoisy,
+ int importance)
throws RemoteException {
bindNotification(pm, iNotificationManager, pkg, notificationChannel,
numUniqueChannelsInRow, sbn, checkSaveListener, onSettingsClick,
onAppSettingsClick, isDeviceProvisioned, isNonblockable,
- false /* isBlockingHelper */, false /* isUserSentimentNegative */);
+ false /* isBlockingHelper */, false /* isUserSentimentNegative */, isNoisy,
+ importance);
}
public void bindNotification(
@@ -173,7 +207,9 @@
boolean isDeviceProvisioned,
boolean isNonblockable,
boolean isForBlockingHelper,
- boolean isUserSentimentNegative)
+ boolean isUserSentimentNegative,
+ boolean isNoisy,
+ int importance)
throws RemoteException {
mINotificationManager = iNotificationManager;
mMetricsLogger = Dependency.get(MetricsLogger.class);
@@ -186,7 +222,10 @@
mCheckSaveListener = checkSaveListener;
mOnSettingsClickListener = onSettingsClick;
mSingleNotificationChannel = notificationChannel;
- mStartingUserImportance = mChosenImportance = mSingleNotificationChannel.getImportance();
+ int channelImportance = mSingleNotificationChannel.getImportance();
+ mStartingChannelImportance = mChosenImportance = channelImportance;
+ mStartingChannelOrNotificationImportance =
+ channelImportance == IMPORTANCE_UNSPECIFIED ? importance : channelImportance;
mNegativeUserSentiment = isUserSentimentNegative;
mIsNonblockable = isNonblockable;
mIsForeground =
@@ -194,6 +233,7 @@
mIsForBlockingHelper = isForBlockingHelper;
mAppUid = mSbn.getUid();
mIsDeviceProvisioned = isDeviceProvisioned;
+ mIsNoisy = isNoisy;
int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
pkg, mAppUid, false /* includeDeleted */);
@@ -306,7 +346,8 @@
}
private boolean hasImportanceChanged() {
- return mSingleNotificationChannel != null && mStartingUserImportance != mChosenImportance;
+ return mSingleNotificationChannel != null
+ && mStartingChannelImportance != mChosenImportance;
}
private void saveImportance() {
@@ -320,34 +361,46 @@
*/
private void updateImportance() {
MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
- mChosenImportance - mStartingUserImportance);
+ mChosenImportance - mStartingChannelImportance);
Handler bgHandler = new Handler(Dependency.get(Dependency.BG_LOOPER));
bgHandler.post(new UpdateImportanceRunnable(mINotificationManager, mPackageName, mAppUid,
mNumUniqueChannelsInRow == 1 ? mSingleNotificationChannel : null,
- mStartingUserImportance, mChosenImportance));
+ mStartingChannelImportance, mChosenImportance));
}
private void bindButtons() {
// Set up stay-in-notification actions
View block = findViewById(R.id.block);
TextView keep = findViewById(R.id.keep);
+ TextView silent = findViewById(R.id.toggle_silent);
View minimize = findViewById(R.id.minimize);
findViewById(R.id.undo).setOnClickListener(mOnUndo);
block.setOnClickListener(mOnStopOrMinimizeNotifications);
keep.setOnClickListener(mOnKeepShowing);
+ silent.setOnClickListener(mOnToggleSilent);
minimize.setOnClickListener(mOnStopOrMinimizeNotifications);
if (mIsNonblockable) {
keep.setText(android.R.string.ok);
block.setVisibility(GONE);
+ silent.setVisibility(GONE);
minimize.setVisibility(GONE);
} else if (mIsForeground) {
block.setVisibility(GONE);
+ silent.setVisibility(GONE);
minimize.setVisibility(VISIBLE);
- } else if (!mIsForeground) {
+ } else {
block.setVisibility(VISIBLE);
+ boolean showToggleSilent = mIsNoisy
+ && NotificationUtils.useNewInterruptionModel(mContext);
+ silent.setVisibility(showToggleSilent ? VISIBLE : GONE);
+ boolean isCurrentlyAlerting =
+ mStartingChannelOrNotificationImportance >= IMPORTANCE_DEFAULT;
+ silent.setText(isCurrentlyAlerting
+ ? R.string.inline_silent_button_silent
+ : R.string.inline_silent_button_alert);
minimize.setVisibility(GONE);
}
@@ -368,7 +421,7 @@
}
}
- private void swapContent(boolean showPrompt) {
+ private void swapContent(@SwapContentAction int action) {
if (mExpandAnimation != null) {
mExpandAnimation.cancel();
}
@@ -378,26 +431,43 @@
TextView confirmationText = findViewById(R.id.confirmation_text);
View header = findViewById(R.id.header);
- if (showPrompt) {
- mChosenImportance = mStartingUserImportance;
- } else if (mIsForeground) {
- mChosenImportance = IMPORTANCE_MIN;
- confirmationText.setText(R.string.notification_channel_minimized);
- } else {
- mChosenImportance = IMPORTANCE_NONE;
- confirmationText.setText(R.string.notification_channel_disabled);
+ switch (action) {
+ case SWAP_CONTENT_UNDO:
+ mChosenImportance = mStartingChannelImportance;
+ break;
+ case SWAP_CONTENT_TOGGLE_SILENT:
+ if (mStartingChannelOrNotificationImportance >= IMPORTANCE_DEFAULT) {
+ mChosenImportance = IMPORTANCE_LOW;
+ confirmationText.setText(R.string.notification_channel_silenced);
+ } else {
+ mChosenImportance = IMPORTANCE_HIGH;
+ confirmationText.setText(R.string.notification_channel_unsilenced);
+ }
+ break;
+ case SWAP_CONTENT_BLOCK:
+ if (mIsForeground) {
+ mChosenImportance = IMPORTANCE_MIN;
+ confirmationText.setText(R.string.notification_channel_minimized);
+ } else {
+ mChosenImportance = IMPORTANCE_NONE;
+ confirmationText.setText(R.string.notification_channel_disabled);
+ }
+ break;
+ default:
+ throw new IllegalArgumentException();
}
+ boolean isUndo = action == SWAP_CONTENT_UNDO;
ObjectAnimator promptAnim = ObjectAnimator.ofFloat(prompt, View.ALPHA,
- prompt.getAlpha(), showPrompt ? 1f : 0f);
- promptAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
+ prompt.getAlpha(), isUndo ? 1f : 0f);
+ promptAnim.setInterpolator(isUndo ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
ObjectAnimator confirmAnim = ObjectAnimator.ofFloat(confirmation, View.ALPHA,
- confirmation.getAlpha(), showPrompt ? 0f : 1f);
- confirmAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
+ confirmation.getAlpha(), isUndo ? 0f : 1f);
+ confirmAnim.setInterpolator(isUndo ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
- prompt.setVisibility(showPrompt ? VISIBLE : GONE);
- confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
- header.setVisibility(showPrompt ? VISIBLE : GONE);
+ prompt.setVisibility(isUndo ? VISIBLE : GONE);
+ confirmation.setVisibility(isUndo ? GONE : VISIBLE);
+ header.setVisibility(isUndo ? VISIBLE : GONE);
mExpandAnimation = new AnimatorSet();
mExpandAnimation.playTogether(promptAnim, confirmAnim);
@@ -413,8 +483,8 @@
@Override
public void onAnimationEnd(Animator animation) {
if (!cancelled) {
- prompt.setVisibility(showPrompt ? VISIBLE : GONE);
- confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
+ prompt.setVisibility(isUndo ? VISIBLE : GONE);
+ confirmation.setVisibility(isUndo ? GONE : VISIBLE);
}
}
});
@@ -428,6 +498,25 @@
}
@Override
+ public void onFinishedClosing() {
+ mStartingChannelImportance = mChosenImportance;
+ if (mChosenImportance != IMPORTANCE_UNSPECIFIED) {
+ mStartingChannelOrNotificationImportance = mChosenImportance;
+ }
+ mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
+
+ View prompt = findViewById(R.id.prompt);
+ ViewGroup confirmation = findViewById(R.id.confirmation);
+ View header = findViewById(R.id.header);
+ prompt.setVisibility(VISIBLE);
+ prompt.setAlpha(1f);
+ confirmation.setVisibility(GONE);
+ confirmation.setAlpha(1f);
+ header.setVisibility(VISIBLE);
+ header.setAlpha(1f);
+ }
+
+ @Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
if (mGutsContainer != null &&
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index c3bf16e..a315bf3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -1124,7 +1124,7 @@
*/
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
private float getExpandTranslationStart() {
- return -mTopPadding + getMinExpansionHeight();
+ return -mTopPadding + getMinExpansionHeight() - mShelf.getIntrinsicHeight();
}
/**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
index 0251f64..8e6bfe3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
@@ -437,15 +437,15 @@
outRanking.getImportance(), outRanking.getImportanceExplanation(),
outRanking.getOverrideGroupKey(), outRanking.getChannel(), null, null,
outRanking.canShowBadge(), outRanking.getUserSentiment(), true,
- false, null, null);
+ false, false, null, null);
} else if (key.equals(TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY)) {
outRanking.populate(key, outRanking.getRank(),
outRanking.matchesInterruptionFilter(),
outRanking.getVisibilityOverride(), 255,
outRanking.getImportance(), outRanking.getImportanceExplanation(),
outRanking.getOverrideGroupKey(), outRanking.getChannel(), null, null,
- outRanking.canShowBadge(), outRanking.getUserSentiment(), true, false, null,
- null);
+ outRanking.canShowBadge(), outRanking.getUserSentiment(), true, false,
+ false, null, null);
} else {
outRanking.populate(key, outRanking.getRank(),
outRanking.matchesInterruptionFilter(),
@@ -453,8 +453,7 @@
outRanking.getImportance(), outRanking.getImportanceExplanation(),
outRanking.getOverrideGroupKey(), NOTIFICATION_CHANNEL, null, null,
outRanking.canShowBadge(), outRanking.getUserSentiment(), false, false,
- null,
- null);
+ false, null, null);
}
return true;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 9c68e7d..9f8a5cc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -167,7 +167,7 @@
0,
NotificationManager.IMPORTANCE_DEFAULT,
null, null,
- null, null, null, true, sentiment, false, false, null, null);
+ null, null, null, true, sentiment, false, false, false, null, null);
return true;
}).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class));
}
@@ -186,7 +186,7 @@
null, null,
null, null, null, true,
NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL, false, false,
- smartActions, null);
+ false, smartActions, null);
return true;
}).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index ee35449..626726d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -19,8 +19,10 @@
import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.service.notification.NotificationListenerService.Ranking
+ .USER_SENTIMENT_NEGATIVE;
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
@@ -34,15 +36,14 @@
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationChannel;
-import android.app.NotificationManager;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Binder;
@@ -57,11 +58,12 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationTestHelper;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager
+ .OnSettingsClickListener;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -71,8 +73,8 @@
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
-import org.mockito.junit.MockitoRule;
import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
/**
* Tests for {@link NotificationGutsManager}.
@@ -84,7 +86,7 @@
private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
private NotificationChannel mTestNotificationChannel = new NotificationChannel(
- TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
+ TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
private TestableLooper mTestableLooper;
private Handler mHandler;
private NotificationTestHelper mHelper;
@@ -297,7 +299,9 @@
eq(false),
eq(false),
eq(true) /* isForBlockingHelper */,
- eq(true) /* isUserSentimentNegative */);
+ eq(true) /* isUserSentimentNegative */,
+ eq(false) /*isNoisy */,
+ eq(0));
}
@Test
@@ -324,7 +328,69 @@
eq(false),
eq(false),
eq(false) /* isForBlockingHelper */,
- eq(true) /* isUserSentimentNegative */);
+ eq(true) /* isUserSentimentNegative */,
+ eq(false) /*isNoisy */,
+ eq(0));
+ }
+
+ @Test
+ public void testInitializeNotificationInfoView_noisy() throws Exception {
+ NotificationInfo notificationInfoView = mock(NotificationInfo.class);
+ ExpandableNotificationRow row = spy(mHelper.createRow());
+ row.setBlockingHelperShowing(true);
+ row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+ row.getEntry().noisy = true;
+ when(row.getIsNonblockable()).thenReturn(false);
+ StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+
+ mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+
+ verify(notificationInfoView).bindNotification(
+ any(PackageManager.class),
+ any(INotificationManager.class),
+ eq(statusBarNotification.getPackageName()),
+ any(NotificationChannel.class),
+ anyInt(),
+ eq(statusBarNotification),
+ any(NotificationInfo.CheckSaveListener.class),
+ any(NotificationInfo.OnSettingsClickListener.class),
+ any(NotificationInfo.OnAppSettingsClickListener.class),
+ eq(false),
+ eq(false),
+ eq(true) /* isForBlockingHelper */,
+ eq(true) /* isUserSentimentNegative */,
+ eq(true) /*isNoisy */,
+ eq(0));
+ }
+
+ @Test
+ public void testInitializeNotificationInfoView_importance() throws Exception {
+ NotificationInfo notificationInfoView = mock(NotificationInfo.class);
+ ExpandableNotificationRow row = spy(mHelper.createRow());
+ row.setBlockingHelperShowing(true);
+ row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+ row.getEntry().importance = IMPORTANCE_DEFAULT;
+ when(row.getIsNonblockable()).thenReturn(false);
+ StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+
+ mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+
+ verify(notificationInfoView).bindNotification(
+ any(PackageManager.class),
+ any(INotificationManager.class),
+ eq(statusBarNotification.getPackageName()),
+ any(NotificationChannel.class),
+ anyInt(),
+ eq(statusBarNotification),
+ any(NotificationInfo.CheckSaveListener.class),
+ any(NotificationInfo.OnSettingsClickListener.class),
+ any(NotificationInfo.OnAppSettingsClickListener.class),
+ eq(false),
+ eq(false),
+ eq(true) /* isForBlockingHelper */,
+ eq(true) /* isUserSentimentNegative */,
+ eq(false) /*isNoisy */,
+ eq(IMPORTANCE_DEFAULT));
}
@Test
@@ -352,7 +418,9 @@
eq(true),
eq(false),
eq(false) /* isForBlockingHelper */,
- eq(true) /* isUserSentimentNegative */);
+ eq(true) /* isUserSentimentNegative */,
+ eq(false) /*isNoisy */,
+ eq(0));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index ca968a8..3744196 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -17,11 +17,14 @@
package com.android.systemui.statusbar.notification.row;
import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME;
+import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
@@ -56,6 +59,7 @@
import android.graphics.drawable.Drawable;
import android.os.IBinder;
import android.os.UserHandle;
+import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
@@ -72,6 +76,7 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -150,6 +155,15 @@
IMPORTANCE_LOW);
mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
new Notification(), UserHandle.CURRENT, null, 0);
+
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
+ }
+
+ @After
+ public void tearDown() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ NOTIFICATION_NEW_INTERRUPTION_MODEL, 0);
}
// TODO: if tests are taking too long replace this with something that makes the animation
@@ -172,7 +186,8 @@
public void testBindNotification_SetsTextApplicationName() throws Exception {
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.pkgname);
assertTrue(textView.getText().toString().contains("App Name"));
assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
@@ -184,7 +199,8 @@
when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
.thenReturn(iconDrawable);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
final ImageView iconView = mNotificationInfo.findViewById(R.id.pkgicon);
assertEquals(iconDrawable, iconView.getDrawable());
}
@@ -192,7 +208,8 @@
@Test
public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
assertEquals(GONE, groupNameView.getVisibility());
final TextView groupDividerView = mNotificationInfo.findViewById(R.id.pkg_group_divider);
@@ -208,7 +225,8 @@
eq("test_group_id"), eq(TEST_PACKAGE_NAME), eq(TEST_UID)))
.thenReturn(notificationChannelGroup);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
assertEquals(View.VISIBLE, groupNameView.getVisibility());
assertEquals("Test Group Name", groupNameView.getText());
@@ -219,7 +237,8 @@
@Test
public void testBindNotification_SetsTextChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(TEST_CHANNEL_NAME, textView.getText());
}
@@ -228,7 +247,7 @@
public void testBindNotification_DefaultChannelDoesNotUseChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, true,
- false);
+ false, false, IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(GONE, textView.getVisibility());
}
@@ -241,7 +260,7 @@
eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(10);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, true,
- false);
+ false, false, IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(VISIBLE, textView.getVisibility());
}
@@ -249,7 +268,8 @@
@Test
public void testBindNotification_UnblockablePackageUsesChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(VISIBLE, textView.getVisibility());
}
@@ -257,18 +277,71 @@
@Test
public void testBindNotification_BlockButton() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
final View block = mNotificationInfo.findViewById(R.id.block);
+ final View toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
final View minimize = mNotificationInfo.findViewById(R.id.minimize);
assertEquals(VISIBLE, block.getVisibility());
+ assertEquals(GONE, toggleSilent.getVisibility());
assertEquals(GONE, minimize.getVisibility());
}
@Test
+ public void testBindNotification_SilenceButton() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true, IMPORTANCE_DEFAULT);
+ final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
+ assertEquals(VISIBLE, toggleSilent.getVisibility());
+ assertEquals(
+ mContext.getString(R.string.inline_silent_button_silent), toggleSilent.getText());
+ }
+
+ @Test
+ public void testBindNotification_UnSilenceButton() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true, IMPORTANCE_LOW);
+ final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
+ assertEquals(VISIBLE, toggleSilent.getVisibility());
+ assertEquals(
+ mContext.getString(R.string.inline_silent_button_alert), toggleSilent.getText());
+ }
+
+ @Test
+ public void testBindNotification_SilenceButton_ChannelImportanceUnspecified() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true, IMPORTANCE_DEFAULT);
+ final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
+ assertEquals(VISIBLE, toggleSilent.getVisibility());
+ assertEquals(
+ mContext.getString(R.string.inline_silent_button_silent), toggleSilent.getText());
+ }
+
+ @Test
+ public void testBindNotification_UnSilenceButton_ChannelImportanceUnspecified()
+ throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true, IMPORTANCE_LOW);
+ final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
+ assertEquals(VISIBLE, toggleSilent.getVisibility());
+ assertEquals(
+ mContext.getString(R.string.inline_silent_button_alert), toggleSilent.getText());
+ }
+
+ @Test
public void testBindNotification_MinButton() throws Exception {
mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
final View block = mNotificationInfo.findViewById(R.id.block);
final View minimize = mNotificationInfo.findViewById(R.id.minimize);
assertEquals(GONE, block.getVisibility());
@@ -283,7 +356,7 @@
(View v, NotificationChannel c, int appUid) -> {
assertEquals(mNotificationChannel, c);
latch.countDown();
- }, null, true, false);
+ }, null, true, false, false, IMPORTANCE_DEFAULT);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
settingsButton.performClick();
@@ -294,7 +367,8 @@
@Test
public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertTrue(settingsButton.getVisibility() != View.VISIBLE);
}
@@ -306,7 +380,7 @@
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
(View v, NotificationChannel c, int appUid) -> {
assertEquals(mNotificationChannel, c);
- }, null, false, false);
+ }, null, false, false, false, IMPORTANCE_DEFAULT);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertTrue(settingsButton.getVisibility() != View.VISIBLE);
}
@@ -314,11 +388,12 @@
@Test
public void testBindNotification_SettingsButtonReappearsAfterSecondBind() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
(View v, NotificationChannel c, int appUid) -> {
- }, null, true, false);
+ }, null, true, false, false, IMPORTANCE_DEFAULT);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertEquals(View.VISIBLE, settingsButton.getVisibility());
}
@@ -326,7 +401,8 @@
@Test
public void testLogBlockingHelperCounter_doesntLogForNormalGutsView() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
verify(mMetricsLogger, times(0)).count(anyString(), anyInt());
}
@@ -335,7 +411,7 @@
public void testLogBlockingHelperCounter_logsForBlockingHelper() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, true,
- true, true);
+ true, true, false, IMPORTANCE_DEFAULT);
mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
verify(mMetricsLogger, times(1)).count(anyString(), anyInt());
}
@@ -348,7 +424,7 @@
(View v, NotificationChannel c, int appUid) -> {
assertEquals(null, c);
latch.countDown();
- }, null, true, true);
+ }, null, true, true, false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.info).performClick();
// Verify that listener was triggered.
@@ -361,7 +437,7 @@
throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
- null, true, true);
+ null, true, true, false, IMPORTANCE_DEFAULT);
final TextView channelNameView =
mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(GONE, channelNameView.getVisibility());
@@ -372,7 +448,7 @@
public void testStopInvisibleIfBundleFromDifferentChannels() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
- null, true, true);
+ null, true, true, false, IMPORTANCE_DEFAULT);
final TextView blockView = mNotificationInfo.findViewById(R.id.block);
assertEquals(GONE, blockView.getVisibility());
}
@@ -381,7 +457,7 @@
public void testbindNotification_BlockingHelper() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, false,
- true, true);
+ true, true, false, IMPORTANCE_DEFAULT);
final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
assertEquals(View.VISIBLE, view.getVisibility());
assertEquals(mContext.getString(R.string.inline_blocking_helper), view.getText());
@@ -390,7 +466,8 @@
@Test
public void testbindNotification_UnblockableTextVisibleWhenAppUnblockable() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
assertEquals(View.VISIBLE, view.getVisibility());
assertEquals(mContext.getString(R.string.notification_unblockable_desc),
@@ -400,7 +477,8 @@
@Test
public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mTestableLooper.processAllMessages();
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), eq(TEST_UID), any());
@@ -410,7 +488,8 @@
public void testDoesNotUpdateNotificationChannelAfterImportanceChanged() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
mTestableLooper.processAllMessages();
@@ -423,7 +502,8 @@
throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
mTestableLooper.processAllMessages();
@@ -432,11 +512,40 @@
}
@Test
+ public void testDoesNotUpdateNotificationChannelAfterImportanceChangedSilenced()
+ throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true, IMPORTANCE_DEFAULT);
+
+ mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ mTestableLooper.processAllMessages();
+ verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), any());
+ }
+
+ @Test
+ public void testDoesNotUpdateNotificationChannelAfterImportanceChangedUnSilenced()
+ throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true, IMPORTANCE_DEFAULT);
+
+ mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ mTestableLooper.processAllMessages();
+ verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), any());
+ }
+
+ @Test
public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged()
throws Exception {
int originalImportance = mNotificationChannel.getImportance();
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.handleCloseControls(true, false);
mTestableLooper.processAllMessages();
@@ -450,7 +559,8 @@
throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.handleCloseControls(true, false);
@@ -468,7 +578,7 @@
TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */ ,
- true, false /* isNonblockable */);
+ true, false /* isNonblockable */, false, /* isNoisy */IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -489,7 +599,7 @@
TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */ ,
- true, false /* isNonblockable */);
+ true, false /* isNonblockable */, false, /* isNoisy */IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -510,7 +620,7 @@
null /* onSettingsClick */, null /* onAppSettingsClick */ ,
true /* provisioned */,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true /* isUserSentimentNegative */);
+ true /* isUserSentimentNegative */, false, /* isNoisy */IMPORTANCE_DEFAULT);
NotificationGuts guts = spy(new NotificationGuts(mContext, null));
when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
@@ -538,7 +648,7 @@
10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */ , true /* provisioned */,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true /* isUserSentimentNegative */);
+ true /* isUserSentimentNegative */, false, /* isNoisy */IMPORTANCE_DEFAULT);
NotificationGuts guts = spy(new NotificationGuts(mContext, null));
when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
@@ -566,7 +676,8 @@
10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */ ,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true, true /* isUserSentimentNegative */);
+ true, true /* isUserSentimentNegative */, false, /* isNoisy */
+ IMPORTANCE_DEFAULT);
mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
@@ -585,7 +696,7 @@
null /* onSettingsClick */, null /* onAppSettingsClick */,
true /* provisioned */,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true /* isUserSentimentNegative */);
+ true /* isUserSentimentNegative */, false, /* isNoisy */IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
mTestableLooper.processAllMessages();
@@ -607,7 +718,8 @@
false /* isNonblockable */,
true /* isForBlockingHelper */,
true,
- false /* isUserSentimentNegative */);
+ false /* isUserSentimentNegative */,
+ false, /* isNoisy */IMPORTANCE_DEFAULT);
NotificationGuts guts = mock(NotificationGuts.class);
doCallRealMethod().when(guts).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
mNotificationInfo.setGutsParent(guts);
@@ -621,7 +733,8 @@
public void testNonBlockableAppDoesNotBecomeBlocked() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -634,7 +747,8 @@
public void testBlockChangedCallsUpdateNotificationChannel() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -666,7 +780,8 @@
true /*provisioned */,
false /* isNonblockable */,
true /* isForBlockingHelper */,
- true /* isUserSentimentNegative */);
+ true /* isUserSentimentNegative */,
+ false, /* isNoisy */IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -687,7 +802,8 @@
public void testNonBlockableAppDoesNotBecomeMin() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -701,7 +817,8 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -721,7 +838,8 @@
public void testKeepUpdatesNotificationChannel() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.handleCloseControls(true, false);
@@ -738,7 +856,8 @@
public void testBlockUndoDoesNotBlockNotificationChannel() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -759,7 +878,8 @@
public void testMinUndoDoesNotMinNotificationChannel() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -777,10 +897,97 @@
}
@Test
+ public void testSilenceCallsUpdateNotificationChannel() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true, IMPORTANCE_DEFAULT);
+
+ mNotificationInfo.findViewById(R.id.toggle_silent).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 testUnSilenceCallsUpdateNotificationChannel() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
+
+ mNotificationInfo.findViewById(R.id.toggle_silent).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_HIGH, updated.getValue().getImportance());
+ }
+
+ @Test
+ public void testSilenceCallsUpdateNotificationChannel_channelImportanceUnspecified()
+ throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true, IMPORTANCE_DEFAULT);
+
+ mNotificationInfo.findViewById(R.id.toggle_silent).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 testUnSilenceCallsUpdateNotificationChannel_channelImportanceUnspecified()
+ throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_LOW);
+
+ mNotificationInfo.findViewById(R.id.toggle_silent).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_HIGH, updated.getValue().getImportance());
+ }
+
+ @Test
public void testCloseControlsDoesNotUpdateiMinIfSaveIsFalse() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -795,7 +1002,8 @@
public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -812,7 +1020,7 @@
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
(Runnable saveImportance, StatusBarNotification sbn) -> {
- }, null, null, true, true);
+ }, null, null, true, true, false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
mTestableLooper.processAllMessages();
@@ -830,7 +1038,7 @@
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
(Runnable saveImportance, StatusBarNotification sbn) -> {
saveImportance.run();
- }, null, null, true, false);
+ }, null, null, true, false, false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
mTestableLooper.processAllMessages();
@@ -866,7 +1074,7 @@
TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null,
(View v, Intent intent) -> {
latch.countDown();
- }, true, false);
+ }, true, false, false, IMPORTANCE_DEFAULT);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(View.VISIBLE, settingsLink.getVisibility());
settingsLink.performClick();
@@ -894,7 +1102,7 @@
TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
(View v, Intent intent) -> {
latch.countDown();
- }, true, false);
+ }, true, false, false, IMPORTANCE_DEFAULT);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(View.VISIBLE, settingsLink.getVisibility());
settingsLink.performClick();
@@ -913,7 +1121,7 @@
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
- null, true, false);
+ null, true, false, false, IMPORTANCE_DEFAULT);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(GONE, settingsLink.getVisibility());
}
@@ -933,7 +1141,8 @@
0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, true, false);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(GONE, settingsLink.getVisibility());
}
@@ -956,7 +1165,7 @@
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, false, true,
- true, true);
+ true, true, false, IMPORTANCE_DEFAULT);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(GONE, settingsLink.getVisibility());
}
@@ -972,7 +1181,8 @@
mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -984,7 +1194,8 @@
public void testUndoText_block() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -993,10 +1204,39 @@
}
@Test
+ public void testUndoText_silence() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ true, IMPORTANCE_DEFAULT);
+
+ mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ waitForUndoButton();
+ TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
+ assertEquals(mContext.getString(R.string.notification_channel_silenced),
+ confirmationText.getText());
+ }
+
+ @Test
+ public void testUndoText_unsilence() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ true, IMPORTANCE_DEFAULT);
+
+ mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ waitForUndoButton();
+ TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
+ assertEquals(mContext.getString(R.string.notification_channel_unsilenced),
+ confirmationText.getText());
+ }
+
+ @Test
public void testNoHeaderOnConfirmation() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -1007,7 +1247,8 @@
public void testHeaderOnUndo() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f87a5f7..b404c41 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -6564,6 +6564,7 @@
Bundle smartActions = new Bundle();
Bundle smartReplies = new Bundle();
Bundle audiblyAlerted = new Bundle();
+ Bundle noisy = new Bundle();
for (int i = 0; i < N; i++) {
NotificationRecord record = mNotificationList.get(i);
if (!isVisibleToListener(record.sbn, info)) {
@@ -6594,6 +6595,7 @@
smartActions.putParcelableArrayList(key, record.getSmartActions());
smartReplies.putCharSequenceArrayList(key, record.getSmartReplies());
audiblyAlerted.putBoolean(key, record.getAudiblyAlerted());
+ noisy.putBoolean(key, record.getSound() != null || record.getVibration() != null);
}
final int M = keys.size();
String[] keysAr = keys.toArray(new String[M]);
@@ -6605,7 +6607,7 @@
return new NotificationRankingUpdate(keysAr, interceptedKeysAr, visibilityOverrides,
suppressedVisualEffects, importanceAr, explanation, overrideGroupKeys,
channels, overridePeople, snoozeCriteria, showBadge, userSentiment, hidden,
- smartActions, smartReplies, audiblyAlerted);
+ smartActions, smartReplies, audiblyAlerted, noisy);
}
boolean hasCompanionDevice(ManagedServiceInfo info) {
diff --git a/services/tests/servicestests/src/com/android/server/job/JobSetTest.java b/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
index e62e07d..6b7634d 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
@@ -29,6 +29,7 @@
import android.content.pm.PackageManagerInternal;
import android.os.Build;
import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
@@ -47,6 +48,7 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
+@Presubmit
public class JobSetTest {
private static final String TAG = JobSetTest.class.getSimpleName();
private static final int SECONDARY_USER_ID_1 = 12;
@@ -64,6 +66,7 @@
final PackageManagerInternal pm = mock(PackageManagerInternal.class);
when(pm.getPackageTargetSdkVersion(anyString()))
.thenReturn(Build.VERSION_CODES.CUR_DEVELOPMENT);
+ LocalServices.removeServiceForTest(PackageManagerInternal.class);
LocalServices.addService(PackageManagerInternal.class, pm);
assumeFalse("Test cannot run in user " + mContext.getUserId(),
mContext.getUserId() == SECONDARY_USER_ID_1
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
index 0d7b584..bcba15d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
@@ -114,6 +114,7 @@
Bundle smartActions = new Bundle();
Bundle smartReplies = new Bundle();
Bundle audiblyAlerted = new Bundle();
+ Bundle noisy = new Bundle();
for (int i = 0; i < mKeys.length; i++) {
String key = mKeys[i];
@@ -134,12 +135,13 @@
smartActions.putParcelableArrayList(key, getSmartActions(key, i));
smartReplies.putCharSequenceArrayList(key, getSmartReplies(key, i));
audiblyAlerted.putBoolean(key, audiblyAlerted(i));
+ noisy.putBoolean(key, getNoisy(i));
}
NotificationRankingUpdate update = new NotificationRankingUpdate(mKeys,
interceptedKeys.toArray(new String[0]), visibilityOverrides,
suppressedVisualEffects, importance, explanation, overrideGroupKeys,
channels, overridePeople, snoozeCriteria, showBadge, userSentiment, mHidden,
- smartActions, smartReplies, audiblyAlerted);
+ smartActions, smartReplies, audiblyAlerted, noisy);
return update;
}
@@ -195,6 +197,10 @@
return index < 2;
}
+ private boolean getNoisy(int index) {
+ return index < 1;
+ }
+
private ArrayList<String> getPeople(String key, int index) {
ArrayList<String> people = new ArrayList<>();
for (int i = 0; i < index; i++) {