diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 448cd2e30ef48..a165621b96967 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -20,17 +20,17 @@
android:id="@+id/notification_header"
android:orientation="horizontal"
android:layout_width="wrap_content"
- android:layout_height="48dp"
+ android:layout_height="@dimen/notification_header_height"
android:clipChildren="false"
- android:paddingTop="10dp"
- android:paddingBottom="11dp"
+ android:paddingTop="@dimen/notification_header_padding_top"
+ android:paddingBottom="@dimen/notification_header_padding_bottom"
android:layout_marginBottom="5dp"
android:paddingStart="@dimen/notification_content_margin_start"
android:paddingEnd="16dp">
16dp
+
+ 48dp
+
45.5dp
+
+ 10dp
+
+ 11dp
+
+
+ 18dp
+
92dp
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index 31bd8b9e415ba..195eb9bafdab4 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -21,110 +21,113 @@
android:layout_height="wrap_content"
android:id="@+id/notification_guts"
android:clickable="true"
- android:gravity="top|start"
android:orientation="vertical"
android:paddingStart="@*android:dimen/notification_content_margin_start"
- android:paddingEnd="8dp"
android:background="@color/notification_guts_bg_color"
android:theme="@*android:style/Theme.DeviceDefault.Light">
+ android:layout_height="@*android:dimen/notification_header_height"
+ android:clipChildren="false"
+ android:paddingTop="@*android:dimen/notification_header_padding_top"
+ android:paddingBottom="@*android:dimen/notification_header_padding_bottom"
+ android:gravity="center_vertical"
+ android:orientation="horizontal" >
+ android:layout_width="@*android:dimen/notification_header_icon_size"
+ android:layout_height="@*android:dimen/notification_header_icon_size"
+ android:layout_marginEnd="3dp"/>
+ android:textAppearance="@*android:style/TextAppearance.Material.Notification.Info"
+ android:layout_marginStart="3dp"
+ android:layout_marginEnd="2dp"
+ android:singleLine="true"/>
+ android:text="@*android:string/notification_header_divider_symbol"/>
+ android:textAppearance="@*android:style/TextAppearance.Material.Notification.Info"
+ android:layout_marginStart="2dp"
+ android:layout_marginEnd="2dp"/>
-
+
-
+
+ android:orientation="vertical">
+
+
+
+
+
+
+
-
-
-
-
-
+ android:layout_marginBottom="8dp" >
-
+ android:layout_height="match_parent"
+ android:layout_marginEnd="8dp"
+ style="@style/TextAppearance.NotificationInfo.Button"/>
+ style="@style/TextAppearance.NotificationInfo.Button"/>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index c9e7e57ecc5a0..1f88aca8ec594 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1340,18 +1340,33 @@
Notifications
-
- " • "
-
You won\'t get these notifications anymore.
+
+ %d notification categories
+
+ defined, describing the current notification channel as "1 out of n categories from this app". -->
- 1 out of %d category from this app
- 1 out of %d categories from this app
+
+
+ %1$s, %2$s
+
+ - %1$s, %2$s, and %3$d other
+ - %1$s, %2$s, and %3$d others
+
+
All Categories
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 9168256eca89f..d6abda6bd4c94 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -349,38 +349,42 @@
- @style/Preference.DropDown.Material
-
-
-
-
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index 5db5498e9bb6d..a9043e4c83bb1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -35,7 +35,6 @@ import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.service.notification.NotificationListenerService;
-import android.service.notification.StatusBarNotification;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@@ -59,6 +58,8 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.GutsIn
import com.android.systemui.statusbar.NotificationGuts.OnSettingsClickListener;
import com.android.systemui.statusbar.stack.StackStateAnimator;
+import java.lang.IllegalArgumentException;
+import java.util.List;
import java.util.Set;
/**
@@ -68,9 +69,11 @@ public class NotificationInfo extends LinearLayout implements GutsContent {
private static final String TAG = "InfoGuts";
private INotificationManager mINotificationManager;
+ private String mPkg;
+ private int mAppUid;
+ private List mNotificationChannels;
+ private NotificationChannel mSingleNotificationChannel;
private int mStartingUserImportance;
- private StatusBarNotification mStatusBarNotification;
- private NotificationChannel mNotificationChannel;
private TextView mNumChannelsView;
private View mChannelDisabledView;
@@ -83,36 +86,42 @@ public class NotificationInfo extends LinearLayout implements GutsContent {
}
public interface OnSettingsClickListener {
- void onClick(View v, int appUid);
+ void onClick(View v, NotificationChannel channel, int appUid);
}
public void bindNotification(final PackageManager pm,
final INotificationManager iNotificationManager,
- final StatusBarNotification sbn, final NotificationChannel channel,
+ final String pkg,
+ final List notificationChannels,
OnSettingsClickListener onSettingsClick,
- OnClickListener onDoneClick, final Set nonBlockablePkgs) {
+ OnClickListener onDoneClick, final Set nonBlockablePkgs)
+ throws RemoteException {
mINotificationManager = iNotificationManager;
- mNotificationChannel = channel;
- mStatusBarNotification = sbn;
- mStartingUserImportance = channel.getImportance();
+ mPkg = pkg;
+ mNotificationChannels = notificationChannels;
+ if (mNotificationChannels.isEmpty()) {
+ throw new IllegalArgumentException("bindNotification requires at least one channel");
+ } else if (mNotificationChannels.size() == 1) {
+ mSingleNotificationChannel = mNotificationChannels.get(0);
+ mStartingUserImportance = mSingleNotificationChannel.getImportance();
+ } else {
+ mSingleNotificationChannel = null;
+ }
- final String pkg = sbn.getPackageName();
- int appUid = -1;
- String appName = pkg;
+ String appName = mPkg;
Drawable pkgicon = null;
CharSequence channelNameText = "";
ApplicationInfo info = null;
try {
- info = pm.getApplicationInfo(pkg,
+ info = pm.getApplicationInfo(mPkg,
PackageManager.MATCH_UNINSTALLED_PACKAGES
| PackageManager.MATCH_DISABLED_COMPONENTS
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| PackageManager.MATCH_DIRECT_BOOT_AWARE);
if (info != null) {
- appUid = info.uid;
+ mAppUid = info.uid;
appName = String.valueOf(pm.getApplicationLabel(info));
pkgicon = pm.getApplicationIcon(info);
-
}
} catch (PackageManager.NameNotFoundException e) {
// app is gone, just show package name and generic icon
@@ -121,38 +130,54 @@ public class NotificationInfo extends LinearLayout implements GutsContent {
((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
int numChannels = 1;
- try {
- numChannels = iNotificationManager.getNumNotificationChannelsForPackage(
- pkg, appUid, false /* includeDeleted */);
- } catch (RemoteException e) {
- Log.e(TAG, e.toString());
- }
+ numChannels = iNotificationManager.getNumNotificationChannelsForPackage(
+ pkg, mAppUid, false /* includeDeleted */);
+ String channelsDescText;
mNumChannelsView = (TextView) (findViewById(R.id.num_channels_desc));
- mNumChannelsView.setText(String.format(mContext.getResources().getQuantityString(
- R.plurals.notification_num_channels_desc, numChannels), numChannels));
+ switch (mNotificationChannels.size()) {
+ case 1:
+ channelsDescText = String.format(mContext.getResources().getQuantityString(
+ R.plurals.notification_num_channels_desc, numChannels), numChannels);
+ break;
+ case 2:
+ channelsDescText = mContext.getString(R.string.notification_channels_list_desc_2,
+ mNotificationChannels.get(0).getName(),
+ mNotificationChannels.get(1).getName());
+ break;
+ default:
+ final int numOthers = mNotificationChannels.size() - 2;
+ channelsDescText = String.format(
+ mContext.getResources().getQuantityString(
+ R.plurals.notification_channels_list_desc_2_and_others, numOthers),
+ mNotificationChannels.get(0).getName(),
+ mNotificationChannels.get(1).getName(),
+ numOthers);
+ }
+ mNumChannelsView.setText(channelsDescText);
- // If this is the placeholder channel, don't use our channel-specific text.
- if (channel.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+ if (mSingleNotificationChannel == null) {
+ // Multiple channels don't use a channel name for the title.
+ channelNameText = mContext.getString(R.string.notification_num_channels,
+ mNotificationChannels.size());
+ } else if (mSingleNotificationChannel.getId()
+ .equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+ // If this is the placeholder channel, don't use our channel-specific text.
channelNameText = mContext.getString(R.string.notification_header_default_channel);
} else {
- channelNameText = channel.getName();
+ channelNameText = mSingleNotificationChannel.getName();
}
((TextView) findViewById(R.id.pkgname)).setText(appName);
((TextView) findViewById(R.id.channel_name)).setText(channelNameText);
// Set group information if this channel has an associated group.
CharSequence groupName = null;
- if (channel.getGroup() != null) {
- try {
- final NotificationChannelGroup notificationChannelGroup =
- iNotificationManager.getNotificationChannelGroupForPackage(
- channel.getGroup(), pkg, appUid);
- if (notificationChannelGroup != null) {
- groupName = notificationChannelGroup.getName();
- }
- } catch (RemoteException e) {
- Log.e(TAG, e.toString());
+ if (mSingleNotificationChannel != null && mSingleNotificationChannel.getGroup() != null) {
+ final NotificationChannelGroup notificationChannelGroup =
+ iNotificationManager.getNotificationChannelGroupForPackage(
+ mSingleNotificationChannel.getGroup(), pkg, mAppUid);
+ if (notificationChannelGroup != null) {
+ groupName = notificationChannelGroup.getName();
}
}
TextView groupNameView = ((TextView) findViewById(R.id.group_name));
@@ -181,15 +206,15 @@ public class NotificationInfo extends LinearLayout implements GutsContent {
// Top-level importance group
mChannelDisabledView = findViewById(R.id.channel_disabled);
- updateImportanceDisplay();
+ updateSecondaryText();
// Settings button.
final TextView settingsButton = (TextView) findViewById(R.id.more_settings);
- if (appUid >= 0 && onSettingsClick != null) {
- final int appUidF = appUid;
+ if (mAppUid >= 0 && onSettingsClick != null) {
+ final int appUidF = mAppUid;
settingsButton.setOnClickListener(
(View view) -> {
- onSettingsClick.onClick(view, appUidF);
+ onSettingsClick.onClick(view, mSingleNotificationChannel, appUidF);
});
if (numChannels > 1) {
settingsButton.setText(R.string.notification_all_categories);
@@ -208,21 +233,24 @@ public class NotificationInfo extends LinearLayout implements GutsContent {
}
public boolean hasImportanceChanged() {
- return mStartingUserImportance != getSelectedImportance();
+ return mSingleNotificationChannel != null &&
+ mStartingUserImportance != getSelectedImportance();
}
private void saveImportance() {
+ if (mSingleNotificationChannel == null) {
+ return;
+ }
int selectedImportance = getSelectedImportance();
if (selectedImportance == mStartingUserImportance) {
return;
}
MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
selectedImportance - mStartingUserImportance);
- mNotificationChannel.setImportance(selectedImportance);
+ mSingleNotificationChannel.setImportance(selectedImportance);
try {
mINotificationManager.updateNotificationChannelForPackage(
- mStatusBarNotification.getPackageName(), mStatusBarNotification.getUid(),
- mNotificationChannel);
+ mPkg, mAppUid, mSingleNotificationChannel);
} catch (RemoteException e) {
// :(
}
@@ -241,26 +269,32 @@ public class NotificationInfo extends LinearLayout implements GutsContent {
mChannelEnabledSwitch = (Switch) findViewById(R.id.channel_enabled_switch);
mChannelEnabledSwitch.setChecked(
mStartingUserImportance != NotificationManager.IMPORTANCE_NONE);
- mChannelEnabledSwitch.setVisibility(nonBlockable ? View.INVISIBLE : View.VISIBLE);
+ final boolean visible = !nonBlockable && mSingleNotificationChannel != null;
+ mChannelEnabledSwitch.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
// Callback when checked.
mChannelEnabledSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (mGutsInteractionListener != null) {
mGutsInteractionListener.onInteraction(NotificationInfo.this);
}
- updateImportanceDisplay();
+ updateSecondaryText();
});
}
- private void updateImportanceDisplay() {
- final boolean disabled = getSelectedImportance() == NotificationManager.IMPORTANCE_NONE;
- mChannelDisabledView.setVisibility(disabled ? View.VISIBLE : View.GONE);
- if (disabled) {
- // To be replaced by disabled text.
+ private void updateSecondaryText() {
+ final boolean defaultChannel = mSingleNotificationChannel != null &&
+ mSingleNotificationChannel.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID);
+ final boolean disabled = mSingleNotificationChannel != null &&
+ getSelectedImportance() == NotificationManager.IMPORTANCE_NONE;
+ if (defaultChannel) {
+ // Don't show any secondary text if this is from the default channel.
+ mChannelDisabledView.setVisibility(View.GONE);
+ mNumChannelsView.setVisibility(View.GONE);
+ } else if (disabled) {
+ mChannelDisabledView.setVisibility(View.VISIBLE);
mNumChannelsView.setVisibility(View.GONE);
- } else if (mNotificationChannel.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
- mNumChannelsView.setVisibility(View.INVISIBLE);
} else {
+ mChannelDisabledView.setVisibility(View.GONE);
mNumChannelsView.setVisibility(View.VISIBLE);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 2c5bd3c4d8a9a..101aee4e9130a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -18,7 +18,6 @@
package com.android.systemui.statusbar.phone;
-
import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.windowStateToString;
@@ -196,8 +195,6 @@ import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
-
-
import com.android.systemui.util.leak.LeakDetector;
import com.android.systemui.volume.VolumeComponent;
@@ -5719,11 +5716,13 @@ public class StatusBar extends SystemUI implements DemoMode,
// The (i) button in the guts that links to the system notification settings for that app
private void startAppNotificationSettingsActivity(String packageName, final int appUid,
- final String channelId) {
+ final NotificationChannel channel) {
final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
intent.putExtra(Settings.EXTRA_APP_UID, appUid);
- intent.putExtra(EXTRA_FRAGMENT_ARG_KEY, channelId);
+ if (channel != null) {
+ intent.putExtra(EXTRA_FRAGMENT_ARG_KEY, channel.getId());
+ }
startNotificationGutsIntent(intent, appUid);
}
@@ -5776,23 +5775,23 @@ public class StatusBar extends SystemUI implements DemoMode,
}
if (item.gutsContent instanceof NotificationInfo) {
- final NotificationChannel channel = row.getEntry().channel;
+ final UserHandle userHandle = sbn.getUser();
PackageManager pmUser = getPackageManagerForUser(mContext,
- sbn.getUser().getIdentifier());
+ userHandle.getIdentifier());
final INotificationManager iNotificationManager = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
final String pkg = sbn.getPackageName();
NotificationInfo info = (NotificationInfo) item.gutsContent;
final NotificationInfo.OnSettingsClickListener onSettingsClick = (View v,
- int appUid) -> {
+ NotificationChannel channel, int appUid) -> {
mMetricsLogger.action(MetricsEvent.ACTION_NOTE_INFO);
guts.resetFalsingCheck();
- startAppNotificationSettingsActivity(pkg, appUid, channel.getId());
+ startAppNotificationSettingsActivity(pkg, appUid, channel);
};
final View.OnClickListener onDoneClick = (View v) -> {
// If the user has security enabled, show challenge if the setting is changed.
if (info.hasImportanceChanged()
- && isLockscreenPublicMode(sbn.getUser().getIdentifier())
+ && isLockscreenPublicMode(userHandle.getIdentifier())
&& (mState == StatusBarState.KEYGUARD
|| mState == StatusBarState.SHADE_LOCKED)) {
OnDismissAction dismissAction = new OnDismissAction() {
@@ -5807,9 +5806,30 @@ public class StatusBar extends SystemUI implements DemoMode,
saveAndCloseNotificationMenu(info, row, guts, v);
}
};
- info.bindNotification(pmUser, iNotificationManager, sbn, channel, onSettingsClick,
- onDoneClick,
- mNonBlockablePkgs);
+
+ ArraySet channels = new ArraySet();
+ channels.add(row.getEntry().channel);
+ if (row.isSummaryWithChildren()) {
+ // If this is a summary, then add in the children notification channels for the
+ // same user and pkg.
+ final List childrenRows = row.getNotificationChildren();
+ final int numChildren = childrenRows.size();
+ for (int i = 0; i < numChildren; i++) {
+ final ExpandableNotificationRow childRow = childrenRows.get(i);
+ final NotificationChannel childChannel = childRow.getEntry().channel;
+ final StatusBarNotification childSbn = childRow.getStatusBarNotification();
+ if (childSbn.getUser().equals(userHandle) &&
+ childSbn.getPackageName().equals(pkg)) {
+ channels.add(childChannel);
+ }
+ }
+ }
+ try {
+ info.bindNotification(pmUser, iNotificationManager, pkg, new ArrayList(channels),
+ onSettingsClick, onDoneClick, mNonBlockablePkgs);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index 726300f79fc1f..8aca546b27302 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -56,8 +56,9 @@ import com.android.systemui.SysuiTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-
+import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
import java.util.concurrent.CountDownLatch;
@SmallTest
@@ -72,14 +73,12 @@ public class NotificationInfoTest extends SysuiTestCase {
private final INotificationManager mMockINotificationManager = mock(INotificationManager.class);
private final PackageManager mMockPackageManager = mock(PackageManager.class);
private NotificationChannel mNotificationChannel;
- private final StatusBarNotification mMockStatusBarNotification =
- mock(StatusBarNotification.class);
+ private NotificationChannel mDefaultNotificationChannel;
@Before
public void setUp() throws Exception {
// Inflate the layout
- final LayoutInflater layoutInflater =
- LayoutInflater.from(mContext);
+ final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
mNotificationInfo = (NotificationInfo) layoutInflater.inflate(R.layout.notification_info,
null);
@@ -92,30 +91,51 @@ public class NotificationInfoTest extends SysuiTestCase {
when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn(
applicationInfo);
- // mMockStatusBarNotification with a test channel.
- mNotificationChannel = new NotificationChannel(
- TEST_CHANNEL, TEST_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
- when(mMockStatusBarNotification.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
+ // Package has one channel by default.
when(mMockINotificationManager.getNumNotificationChannelsForPackage(
eq(TEST_PACKAGE_NAME), anyInt(), anyBoolean())).thenReturn(1);
+
+ // Some test channels.
+ mNotificationChannel = new NotificationChannel(
+ TEST_CHANNEL, TEST_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
+ mDefaultNotificationChannel = new NotificationChannel(
+ NotificationChannel.DEFAULT_CHANNEL_ID, TEST_CHANNEL_NAME,
+ NotificationManager.IMPORTANCE_LOW);
}
private CharSequence getStringById(int resId) {
return mContext.getString(resId);
}
- private CharSequence getNumChannelsString(int numChannels) {
+ private CharSequence getNumChannelsDescString(int numChannels) {
return String.format(
mContext.getResources().getQuantityString(
R.plurals.notification_num_channels_desc, numChannels),
numChannels);
}
+ private CharSequence getChannelsListDescString(NotificationChannel... channels) {
+ if (channels.length == 2) {
+ return mContext.getString(R.string.notification_channels_list_desc_2,
+ channels[0].getName(), channels[1].getName());
+ } else {
+ final int numOthers = channels.length - 2;
+ return String.format(
+ mContext.getResources().getQuantityString(
+ R.plurals.notification_channels_list_desc_2_and_others, numOthers),
+ channels[0].getName(), channels[1].getName(), numOthers);
+ }
+ }
+
+ private CharSequence getNumChannelsString(int numChannels) {
+ return mContext.getString(R.string.notification_num_channels, numChannels);
+ }
+
@Test
public void testBindNotification_SetsTextApplicationName() throws Exception {
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null, null);
final TextView textView = (TextView) mNotificationInfo.findViewById(R.id.pkgname);
assertTrue(textView.getText().toString().contains("App Name"));
}
@@ -126,7 +146,7 @@ public class NotificationInfoTest extends SysuiTestCase {
when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
.thenReturn(iconDrawable);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null, null);
final ImageView iconView = (ImageView) mNotificationInfo.findViewById(R.id.pkgicon);
assertEquals(iconDrawable, iconView.getDrawable());
}
@@ -134,7 +154,7 @@ public class NotificationInfoTest extends SysuiTestCase {
@Test
public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null, null);
final TextView groupNameView = (TextView) mNotificationInfo.findViewById(R.id.group_name);
assertEquals(View.GONE, groupNameView.getVisibility());
final TextView groupDividerView =
@@ -151,7 +171,7 @@ public class NotificationInfoTest extends SysuiTestCase {
eq("test_group_id"), eq(TEST_PACKAGE_NAME), anyInt()))
.thenReturn(notificationChannelGroup);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null, null);
final TextView groupNameView = (TextView) mNotificationInfo.findViewById(R.id.group_name);
assertEquals(View.VISIBLE, groupNameView.getVisibility());
assertEquals("Test Group Name", groupNameView.getText());
@@ -163,7 +183,7 @@ public class NotificationInfoTest extends SysuiTestCase {
@Test
public void testBindNotification_SetsTextChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null, null);
final TextView textView = (TextView) mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(TEST_CHANNEL_NAME, textView.getText());
}
@@ -172,8 +192,29 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel,
- (View v, int appUid) -> { latch.countDown(); }, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
+ (View v, NotificationChannel c, int appUid) -> {
+ assertEquals(mNotificationChannel, c);
+ latch.countDown();
+ }, null, null);
+
+ final TextView settingsButton =
+ (TextView) mNotificationInfo.findViewById(R.id.more_settings);
+ settingsButton.performClick();
+ // Verify that listener was triggered.
+ assertEquals(0, latch.getCount());
+ }
+
+ @Test
+ public void testOnClickListenerPassesNullChannelForBundle() throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME,
+ Arrays.asList(mNotificationChannel, mDefaultNotificationChannel),
+ (View v, NotificationChannel c, int appUid) -> {
+ assertEquals(null, c);
+ latch.countDown();
+ }, null, null);
final TextView settingsButton =
(TextView) mNotificationInfo.findViewById(R.id.more_settings);
@@ -185,8 +226,8 @@ public class NotificationInfoTest extends SysuiTestCase {
@Test
public void testBindNotification_SettingsTextWithOneChannel() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, (View v, int appUid) -> {}, null,
- null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
+ (View v, NotificationChannel c, int appUid) -> {}, null, null);
final TextView settingsButton =
(TextView) mNotificationInfo.findViewById(R.id.more_settings);
assertEquals(getStringById(R.string.notification_more_settings), settingsButton.getText());
@@ -197,8 +238,8 @@ public class NotificationInfoTest extends SysuiTestCase {
when(mMockINotificationManager.getNumNotificationChannelsForPackage(
eq(TEST_PACKAGE_NAME), anyInt(), anyBoolean())).thenReturn(2);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, (View v, int appUid) -> {}, null,
- null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
+ (View v, NotificationChannel c, int appUid) -> {}, null, null);
final TextView settingsButton =
(TextView) mNotificationInfo.findViewById(R.id.more_settings);
assertEquals(getStringById(R.string.notification_all_categories), settingsButton.getText());
@@ -208,7 +249,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_SetsOnClickListenerForDone() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null,
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null,
(View v) -> { latch.countDown(); },
null);
@@ -220,11 +261,8 @@ public class NotificationInfoTest extends SysuiTestCase {
@Test
public void testBindNotification_NumChannelsTextHiddenWhenDefaultChannel() throws Exception {
- final NotificationChannel defaultChannel = new NotificationChannel(
- NotificationChannel.DEFAULT_CHANNEL_ID, TEST_CHANNEL_NAME,
- NotificationManager.IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, defaultChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mDefaultNotificationChannel), null, null, null);
final TextView numChannelsView =
(TextView) mNotificationInfo.findViewById(R.id.num_channels_desc);
assertTrue(numChannelsView.getVisibility() != View.VISIBLE);
@@ -234,11 +272,11 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_NumChannelsTextDisplaysWhenNotDefaultChannel()
throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null, null);
final TextView numChannelsView =
(TextView) mNotificationInfo.findViewById(R.id.num_channels_desc);
assertEquals(numChannelsView.getVisibility(), View.VISIBLE);
- assertEquals(getNumChannelsString(1), numChannelsView.getText());
+ assertEquals(getNumChannelsDescString(1), numChannelsView.getText());
}
@Test
@@ -247,16 +285,90 @@ public class NotificationInfoTest extends SysuiTestCase {
when(mMockINotificationManager.getNumNotificationChannelsForPackage(
eq(TEST_PACKAGE_NAME), anyInt(), anyBoolean())).thenReturn(2);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null, null);
final TextView numChannelsView =
(TextView) mNotificationInfo.findViewById(R.id.num_channels_desc);
- assertEquals(getNumChannelsString(2), numChannelsView.getText());
+ assertEquals(getNumChannelsDescString(2), numChannelsView.getText());
+ }
+
+ @Test
+ @UiThreadTest
+ public void testBindNotification_NumChannelsTextListsChannelsWhenTwoInBundle()
+ throws Exception {
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel, mDefaultNotificationChannel),
+ null, null, null);
+ final TextView numChannelsView =
+ (TextView) mNotificationInfo.findViewById(R.id.num_channels_desc);
+ assertEquals(getChannelsListDescString(mNotificationChannel, mDefaultNotificationChannel),
+ numChannelsView.getText());
+ }
+
+ @Test
+ @UiThreadTest
+ public void testBindNotification_NumChannelsTextListsChannelsWhenThreeInBundle()
+ throws Exception {
+ NotificationChannel thirdChannel = new NotificationChannel(
+ "third_channel", "third_channel", NotificationManager.IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME,
+ Arrays.asList(mNotificationChannel, mDefaultNotificationChannel, thirdChannel),
+ null, null, null);
+ final TextView numChannelsView =
+ (TextView) mNotificationInfo.findViewById(R.id.num_channels_desc);
+ assertEquals(
+ getChannelsListDescString(mNotificationChannel, mDefaultNotificationChannel,
+ thirdChannel),
+ numChannelsView.getText());
+ }
+
+ @Test
+ @UiThreadTest
+ public void testBindNotification_NumChannelsTextListsChannelsWhenFourInBundle()
+ throws Exception {
+ NotificationChannel thirdChannel = new NotificationChannel(
+ "third_channel", "third_channel", NotificationManager.IMPORTANCE_LOW);
+ NotificationChannel fourthChannel = new NotificationChannel(
+ "fourth_channel", "fourth_channel", NotificationManager.IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME,
+ Arrays.asList(mNotificationChannel, mDefaultNotificationChannel, thirdChannel,
+ fourthChannel),
+ null, null, null);
+ final TextView numChannelsView =
+ (TextView) mNotificationInfo.findViewById(R.id.num_channels_desc);
+ assertEquals(
+ getChannelsListDescString(mNotificationChannel, mDefaultNotificationChannel,
+ thirdChannel, fourthChannel),
+ numChannelsView.getText());
+ }
+
+ @Test
+ @UiThreadTest
+ public void testBindNotification_ChannelNameChangesWhenBundleFromDifferentChannels()
+ throws Exception {
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel, mDefaultNotificationChannel),
+ null, null, null);
+ final TextView channelNameView =
+ (TextView) mNotificationInfo.findViewById(R.id.channel_name);
+ assertEquals(getNumChannelsString(2), channelNameView.getText());
+ }
+
+ @Test
+ @UiThreadTest
+ public void testEnabledSwitchInvisibleIfBundleFromDifferentChannels() throws Exception {
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel, mDefaultNotificationChannel),
+ null, null, null);
+ Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
+ assertEquals(View.INVISIBLE, enabledSwitch.getVisibility());
}
@Test
public void testbindNotification_ChannelDisabledTextGoneWhenNotDisabled() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null, null);
final TextView channelDisabledView =
(TextView) mNotificationInfo.findViewById(R.id.channel_disabled);
assertEquals(channelDisabledView.getVisibility(), View.GONE);
@@ -266,7 +378,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testbindNotification_ChannelDisabledTextVisibleWhenDisabled() throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_NONE);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null, null);
final TextView channelDisabledView =
(TextView) mNotificationInfo.findViewById(R.id.channel_disabled);
assertEquals(channelDisabledView.getVisibility(), View.VISIBLE);
@@ -277,9 +389,21 @@ public class NotificationInfoTest extends SysuiTestCase {
}
@Test
+ @UiThreadTest
+ public void testBindNotification_ChannelDisabledTextHiddenWhenDefaultChannel()
+ throws Exception {
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, Arrays.asList(mDefaultNotificationChannel), null, null, null);
+ final TextView channelDisabledView =
+ (TextView) mNotificationInfo.findViewById(R.id.channel_disabled);
+ assertTrue(channelDisabledView.getVisibility() != View.VISIBLE);
+ }
+
+ @Test
+ @UiThreadTest
public void testHasImportanceChanged_DefaultsToFalse() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null, null);
assertFalse(mNotificationInfo.hasImportanceChanged());
}
@@ -287,7 +411,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testHasImportanceChanged_ReturnsTrueAfterChannelDisabled() throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null, null);
// Find the high button and check it.
Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
enabledSwitch.setChecked(false);
@@ -297,7 +421,7 @@ public class NotificationInfoTest extends SysuiTestCase {
@Test
public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null, null);
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), anyInt(), any());
}
@@ -306,7 +430,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testDoesNotUpdateNotificationChannelAfterImportanceChanged() throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null, null);
Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
enabledSwitch.setChecked(false);
@@ -318,7 +442,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged()
throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null, null);
mNotificationInfo.handleCloseControls(true);
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
@@ -330,7 +454,7 @@ public class NotificationInfoTest extends SysuiTestCase {
throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null, null);
mNotificationInfo.handleCloseControls(true);
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
@@ -341,7 +465,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testEnabledSwitchOnByDefault() throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null, null);
Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
assertTrue(enabledSwitch.isChecked());
@@ -351,7 +475,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testEnabledButtonOffWhenAlreadyBanned() throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_NONE);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null, null);
Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
assertFalse(enabledSwitch.isChecked());
@@ -361,7 +485,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testEnabledSwitchVisibleByDefault() throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null, null);
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null, null);
Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
assertEquals(View.VISIBLE, enabledSwitch.getVisibility());
@@ -371,18 +495,29 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testEnabledSwitchInvisibleIfNonBlockable() throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null,
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null,
Collections.singleton(TEST_PACKAGE_NAME));
Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
assertEquals(View.INVISIBLE, enabledSwitch.getVisibility());
}
+ @Test
+ public void testNonBlockableAppDoesNotBecomeBlocked() throws Exception {
+ mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null,
+ Collections.singleton(TEST_PACKAGE_NAME));
+ mNotificationInfo.handleCloseControls(true);
+ verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+ anyString(), anyInt(), any());
+ }
+
@Test
public void testEnabledSwitchChangedCallsUpdateNotificationChannel() throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null,
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null,
Collections.singleton(TEST_PACKAGE_NAME));
Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
@@ -396,7 +531,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception {
mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- mMockStatusBarNotification, mNotificationChannel, null, null,
+ TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel), null, null,
Collections.singleton(TEST_PACKAGE_NAME));
Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);