Loading core/java/android/app/NotificationChannel.java +25 −1 Original line number Diff line number Diff line Loading @@ -71,6 +71,7 @@ public final class NotificationChannel implements Parcelable { private static final String ATT_SHOW_BADGE = "show_badge"; private static final String ATT_USER_LOCKED = "locked"; private static final String ATT_GROUP = "group"; private static final String ATT_BLOCKABLE_SYSTEM = "blockable_system"; private static final String DELIMITER = ","; /** Loading Loading @@ -140,6 +141,7 @@ public final class NotificationChannel implements Parcelable { private boolean mDeleted = DEFAULT_DELETED; private String mGroup; private AudioAttributes mAudioAttributes = Notification.AUDIO_ATTRIBUTES_DEFAULT; private boolean mBlockableSystem = false; /** * Creates a notification channel. Loading Loading @@ -199,6 +201,7 @@ public final class NotificationChannel implements Parcelable { } mAudioAttributes = in.readInt() > 0 ? AudioAttributes.CREATOR.createFromParcel(in) : null; mLightColor = in.readInt(); mBlockableSystem = in.readBoolean(); } @Override Loading Loading @@ -249,6 +252,7 @@ public final class NotificationChannel implements Parcelable { dest.writeInt(0); } dest.writeInt(mLightColor); dest.writeBoolean(mBlockableSystem); } /** Loading @@ -272,6 +276,12 @@ public final class NotificationChannel implements Parcelable { mDeleted = deleted; } /** * @hide */ public void setBlockableSystem(boolean blockableSystem) { mBlockableSystem = blockableSystem; } // Modifiable by apps post channel creation /** Loading Loading @@ -421,7 +431,6 @@ public final class NotificationChannel implements Parcelable { this.mLockscreenVisibility = lockscreenVisibility; } /** * Returns the id of this channel. */ Loading Loading @@ -546,6 +555,13 @@ public final class NotificationChannel implements Parcelable { return mUserLockedFields; } /** * @hide */ public boolean isBlockableSystem() { return mBlockableSystem; } /** * @hide */ Loading @@ -565,6 +581,7 @@ public final class NotificationChannel implements Parcelable { setDeleted(safeBool(parser, ATT_DELETED, false)); setGroup(parser.getAttributeValue(null, ATT_GROUP)); lockFields(safeInt(parser, ATT_USER_LOCKED, 0)); setBlockableSystem(safeBool(parser, ATT_BLOCKABLE_SYSTEM, false)); } /** Loading Loading @@ -625,6 +642,9 @@ public final class NotificationChannel implements Parcelable { if (getGroup() != null) { out.attribute(null, ATT_GROUP, getGroup()); } if (isBlockableSystem()) { out.attribute(null, ATT_BLOCKABLE_SYSTEM, Boolean.toString(isBlockableSystem())); } out.endTag(null, TAG_CHANNEL); } Loading Loading @@ -665,6 +685,7 @@ public final class NotificationChannel implements Parcelable { record.put(ATT_SHOW_BADGE, Boolean.toString(canShowBadge())); record.put(ATT_DELETED, Boolean.toString(isDeleted())); record.put(ATT_GROUP, getGroup()); record.put(ATT_BLOCKABLE_SYSTEM, isBlockableSystem()); return record; } Loading Loading @@ -764,6 +785,7 @@ public final class NotificationChannel implements Parcelable { if (mVibrationEnabled != that.mVibrationEnabled) return false; if (mShowBadge != that.mShowBadge) return false; if (isDeleted() != that.isDeleted()) return false; if (isBlockableSystem() != that.isBlockableSystem()) return false; if (getId() != null ? !getId().equals(that.getId()) : that.getId() != null) return false; if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) { return false; Loading Loading @@ -802,6 +824,7 @@ public final class NotificationChannel implements Parcelable { result = 31 * result + (isDeleted() ? 1 : 0); result = 31 * result + (getGroup() != null ? getGroup().hashCode() : 0); result = 31 * result + (getAudioAttributes() != null ? getAudioAttributes().hashCode() : 0); result = 31 * result + (isBlockableSystem() ? 1 : 0); return result; } Loading @@ -824,6 +847,7 @@ public final class NotificationChannel implements Parcelable { ", mDeleted=" + mDeleted + ", mGroup='" + mGroup + '\'' + ", mAudioAttributes=" + mAudioAttributes + ", mBlockableSystem=" + mBlockableSystem + '}'; } } packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java +3 −1 Original line number Diff line number Diff line Loading @@ -221,7 +221,9 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G boolean nonBlockable = false; try { final PackageInfo pkgInfo = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES); nonBlockable = Utils.isSystemPackage(getResources(), pm, pkgInfo); nonBlockable = Utils.isSystemPackage(getResources(), pm, pkgInfo) && (mSingleNotificationChannel == null || !mSingleNotificationChannel.isBlockableSystem()); } catch (PackageManager.NameNotFoundException e) { // unlikely. } Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java +50 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.systemui.statusbar; import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNull; Loading Loading @@ -74,6 +76,7 @@ import java.util.concurrent.CountDownLatch; @UiThreadTest public class NotificationInfoTest extends SysuiTestCase { private static final String TEST_PACKAGE_NAME = "test_package"; private static final String TEST_SYSTEM_PACKAGE_NAME = PRINT_SPOOLER_PACKAGE_NAME; private static final int TEST_UID = 1; private static final String TEST_CHANNEL = "test_channel"; private static final String TEST_CHANNEL_NAME = "TEST CHANNEL NAME"; Loading @@ -95,11 +98,18 @@ public class NotificationInfoTest extends SysuiTestCase { // PackageManager must return a packageInfo and applicationInfo. final PackageInfo packageInfo = new PackageInfo(); packageInfo.packageName = TEST_PACKAGE_NAME; when(mMockPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(packageInfo); when(mMockPackageManager.getPackageInfo(eq(TEST_PACKAGE_NAME), anyInt())) .thenReturn(packageInfo); final ApplicationInfo applicationInfo = new ApplicationInfo(); applicationInfo.uid = TEST_UID; // non-zero when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn( applicationInfo); final PackageInfo systemPackageInfo = new PackageInfo(); systemPackageInfo.packageName = TEST_SYSTEM_PACKAGE_NAME; when(mMockPackageManager.getPackageInfo(eq(TEST_SYSTEM_PACKAGE_NAME), anyInt())) .thenReturn(systemPackageInfo); when(mMockPackageManager.getPackageInfo(eq("android"), anyInt())) .thenReturn(packageInfo); // Package has one channel by default. when(mMockINotificationManager.getNumNotificationChannelsForPackage( Loading Loading @@ -604,6 +614,45 @@ public class NotificationInfoTest extends SysuiTestCase { assertEquals(View.INVISIBLE, enabledSwitch.getVisibility()); } @Test public void testEnabledSwitchInvisibleIfNonBlockableSystemChannel() throws Exception { mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW); mNotificationChannel.setBlockableSystem(false); mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, TEST_SYSTEM_PACKAGE_NAME, Arrays.asList(mNotificationChannel), mNotificationChannel.getImportance(), mSbn, null, null, null, null, null); Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch); assertEquals(View.INVISIBLE, enabledSwitch.getVisibility()); } @Test public void testEnabledSwitchVisibleIfBlockableSystemChannel() throws Exception { mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW); mNotificationChannel.setBlockableSystem(true); mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, TEST_SYSTEM_PACKAGE_NAME, Arrays.asList(mNotificationChannel), mNotificationChannel.getImportance(), mSbn, null, null, null, null, null); Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch); assertEquals(View.VISIBLE, enabledSwitch.getVisibility()); } @Test public void testEnabledSwitchInvisibleIfMultiChannelSummary() throws Exception { mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW); mNotificationChannel.setBlockableSystem(true); mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel, mDefaultNotificationChannel), mNotificationChannel.getImportance(), mSbn, null, null, 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); Loading services/core/java/com/android/server/notification/RankingHelper.java +2 −1 Original line number Diff line number Diff line Loading @@ -551,7 +551,7 @@ public class RankingHelper implements RankingConfig { } NotificationChannel existing = r.channels.get(channel.getId()); // Keep existing settings, except deleted status and name // Keep most of the existing settings if (existing != null && fromTargetApp) { if (existing.isDeleted()) { existing.setDeleted(false); Loading @@ -559,6 +559,7 @@ public class RankingHelper implements RankingConfig { existing.setName(channel.getName().toString()); existing.setDescription(channel.getDescription()); existing.setBlockableSystem(channel.isBlockableSystem()); MetricsLogger.action(getChannelLog(channel, pkg)); updateConfig(); Loading services/core/java/com/android/server/wm/AlertWindowNotification.java +3 −5 Original line number Diff line number Diff line Loading @@ -100,7 +100,7 @@ class AlertWindowNotification { final String appName = (aInfo != null) ? pm.getApplicationLabel(aInfo).toString() : mPackageName; createNotificationChannelIfNeeded(context, appName); createNotificationChannel(context, appName); final String message = context.getString(R.string.alert_windows_notification_message, appName); Loading Loading @@ -134,16 +134,14 @@ class AlertWindowNotification { return PendingIntent.getActivity(context, mRequestCode, intent, FLAG_CANCEL_CURRENT); } private void createNotificationChannelIfNeeded(Context context, String appName) { if (mNotificationManager.getNotificationChannel(mNotificationTag) != null) { return; } private void createNotificationChannel(Context context, String appName) { final String nameChannel = context.getString(R.string.alert_windows_notification_channel_name, appName); final NotificationChannel channel = new NotificationChannel(mNotificationTag, nameChannel, IMPORTANCE_MIN); channel.enableLights(false); channel.enableVibration(false); channel.setBlockableSystem(true); mNotificationManager.createNotificationChannel(channel); } Loading Loading
core/java/android/app/NotificationChannel.java +25 −1 Original line number Diff line number Diff line Loading @@ -71,6 +71,7 @@ public final class NotificationChannel implements Parcelable { private static final String ATT_SHOW_BADGE = "show_badge"; private static final String ATT_USER_LOCKED = "locked"; private static final String ATT_GROUP = "group"; private static final String ATT_BLOCKABLE_SYSTEM = "blockable_system"; private static final String DELIMITER = ","; /** Loading Loading @@ -140,6 +141,7 @@ public final class NotificationChannel implements Parcelable { private boolean mDeleted = DEFAULT_DELETED; private String mGroup; private AudioAttributes mAudioAttributes = Notification.AUDIO_ATTRIBUTES_DEFAULT; private boolean mBlockableSystem = false; /** * Creates a notification channel. Loading Loading @@ -199,6 +201,7 @@ public final class NotificationChannel implements Parcelable { } mAudioAttributes = in.readInt() > 0 ? AudioAttributes.CREATOR.createFromParcel(in) : null; mLightColor = in.readInt(); mBlockableSystem = in.readBoolean(); } @Override Loading Loading @@ -249,6 +252,7 @@ public final class NotificationChannel implements Parcelable { dest.writeInt(0); } dest.writeInt(mLightColor); dest.writeBoolean(mBlockableSystem); } /** Loading @@ -272,6 +276,12 @@ public final class NotificationChannel implements Parcelable { mDeleted = deleted; } /** * @hide */ public void setBlockableSystem(boolean blockableSystem) { mBlockableSystem = blockableSystem; } // Modifiable by apps post channel creation /** Loading Loading @@ -421,7 +431,6 @@ public final class NotificationChannel implements Parcelable { this.mLockscreenVisibility = lockscreenVisibility; } /** * Returns the id of this channel. */ Loading Loading @@ -546,6 +555,13 @@ public final class NotificationChannel implements Parcelable { return mUserLockedFields; } /** * @hide */ public boolean isBlockableSystem() { return mBlockableSystem; } /** * @hide */ Loading @@ -565,6 +581,7 @@ public final class NotificationChannel implements Parcelable { setDeleted(safeBool(parser, ATT_DELETED, false)); setGroup(parser.getAttributeValue(null, ATT_GROUP)); lockFields(safeInt(parser, ATT_USER_LOCKED, 0)); setBlockableSystem(safeBool(parser, ATT_BLOCKABLE_SYSTEM, false)); } /** Loading Loading @@ -625,6 +642,9 @@ public final class NotificationChannel implements Parcelable { if (getGroup() != null) { out.attribute(null, ATT_GROUP, getGroup()); } if (isBlockableSystem()) { out.attribute(null, ATT_BLOCKABLE_SYSTEM, Boolean.toString(isBlockableSystem())); } out.endTag(null, TAG_CHANNEL); } Loading Loading @@ -665,6 +685,7 @@ public final class NotificationChannel implements Parcelable { record.put(ATT_SHOW_BADGE, Boolean.toString(canShowBadge())); record.put(ATT_DELETED, Boolean.toString(isDeleted())); record.put(ATT_GROUP, getGroup()); record.put(ATT_BLOCKABLE_SYSTEM, isBlockableSystem()); return record; } Loading Loading @@ -764,6 +785,7 @@ public final class NotificationChannel implements Parcelable { if (mVibrationEnabled != that.mVibrationEnabled) return false; if (mShowBadge != that.mShowBadge) return false; if (isDeleted() != that.isDeleted()) return false; if (isBlockableSystem() != that.isBlockableSystem()) return false; if (getId() != null ? !getId().equals(that.getId()) : that.getId() != null) return false; if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) { return false; Loading Loading @@ -802,6 +824,7 @@ public final class NotificationChannel implements Parcelable { result = 31 * result + (isDeleted() ? 1 : 0); result = 31 * result + (getGroup() != null ? getGroup().hashCode() : 0); result = 31 * result + (getAudioAttributes() != null ? getAudioAttributes().hashCode() : 0); result = 31 * result + (isBlockableSystem() ? 1 : 0); return result; } Loading @@ -824,6 +847,7 @@ public final class NotificationChannel implements Parcelable { ", mDeleted=" + mDeleted + ", mGroup='" + mGroup + '\'' + ", mAudioAttributes=" + mAudioAttributes + ", mBlockableSystem=" + mBlockableSystem + '}'; } }
packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java +3 −1 Original line number Diff line number Diff line Loading @@ -221,7 +221,9 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G boolean nonBlockable = false; try { final PackageInfo pkgInfo = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES); nonBlockable = Utils.isSystemPackage(getResources(), pm, pkgInfo); nonBlockable = Utils.isSystemPackage(getResources(), pm, pkgInfo) && (mSingleNotificationChannel == null || !mSingleNotificationChannel.isBlockableSystem()); } catch (PackageManager.NameNotFoundException e) { // unlikely. } Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java +50 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.systemui.statusbar; import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNull; Loading Loading @@ -74,6 +76,7 @@ import java.util.concurrent.CountDownLatch; @UiThreadTest public class NotificationInfoTest extends SysuiTestCase { private static final String TEST_PACKAGE_NAME = "test_package"; private static final String TEST_SYSTEM_PACKAGE_NAME = PRINT_SPOOLER_PACKAGE_NAME; private static final int TEST_UID = 1; private static final String TEST_CHANNEL = "test_channel"; private static final String TEST_CHANNEL_NAME = "TEST CHANNEL NAME"; Loading @@ -95,11 +98,18 @@ public class NotificationInfoTest extends SysuiTestCase { // PackageManager must return a packageInfo and applicationInfo. final PackageInfo packageInfo = new PackageInfo(); packageInfo.packageName = TEST_PACKAGE_NAME; when(mMockPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(packageInfo); when(mMockPackageManager.getPackageInfo(eq(TEST_PACKAGE_NAME), anyInt())) .thenReturn(packageInfo); final ApplicationInfo applicationInfo = new ApplicationInfo(); applicationInfo.uid = TEST_UID; // non-zero when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn( applicationInfo); final PackageInfo systemPackageInfo = new PackageInfo(); systemPackageInfo.packageName = TEST_SYSTEM_PACKAGE_NAME; when(mMockPackageManager.getPackageInfo(eq(TEST_SYSTEM_PACKAGE_NAME), anyInt())) .thenReturn(systemPackageInfo); when(mMockPackageManager.getPackageInfo(eq("android"), anyInt())) .thenReturn(packageInfo); // Package has one channel by default. when(mMockINotificationManager.getNumNotificationChannelsForPackage( Loading Loading @@ -604,6 +614,45 @@ public class NotificationInfoTest extends SysuiTestCase { assertEquals(View.INVISIBLE, enabledSwitch.getVisibility()); } @Test public void testEnabledSwitchInvisibleIfNonBlockableSystemChannel() throws Exception { mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW); mNotificationChannel.setBlockableSystem(false); mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, TEST_SYSTEM_PACKAGE_NAME, Arrays.asList(mNotificationChannel), mNotificationChannel.getImportance(), mSbn, null, null, null, null, null); Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch); assertEquals(View.INVISIBLE, enabledSwitch.getVisibility()); } @Test public void testEnabledSwitchVisibleIfBlockableSystemChannel() throws Exception { mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW); mNotificationChannel.setBlockableSystem(true); mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, TEST_SYSTEM_PACKAGE_NAME, Arrays.asList(mNotificationChannel), mNotificationChannel.getImportance(), mSbn, null, null, null, null, null); Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch); assertEquals(View.VISIBLE, enabledSwitch.getVisibility()); } @Test public void testEnabledSwitchInvisibleIfMultiChannelSummary() throws Exception { mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW); mNotificationChannel.setBlockableSystem(true); mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager, TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel, mDefaultNotificationChannel), mNotificationChannel.getImportance(), mSbn, null, null, 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); Loading
services/core/java/com/android/server/notification/RankingHelper.java +2 −1 Original line number Diff line number Diff line Loading @@ -551,7 +551,7 @@ public class RankingHelper implements RankingConfig { } NotificationChannel existing = r.channels.get(channel.getId()); // Keep existing settings, except deleted status and name // Keep most of the existing settings if (existing != null && fromTargetApp) { if (existing.isDeleted()) { existing.setDeleted(false); Loading @@ -559,6 +559,7 @@ public class RankingHelper implements RankingConfig { existing.setName(channel.getName().toString()); existing.setDescription(channel.getDescription()); existing.setBlockableSystem(channel.isBlockableSystem()); MetricsLogger.action(getChannelLog(channel, pkg)); updateConfig(); Loading
services/core/java/com/android/server/wm/AlertWindowNotification.java +3 −5 Original line number Diff line number Diff line Loading @@ -100,7 +100,7 @@ class AlertWindowNotification { final String appName = (aInfo != null) ? pm.getApplicationLabel(aInfo).toString() : mPackageName; createNotificationChannelIfNeeded(context, appName); createNotificationChannel(context, appName); final String message = context.getString(R.string.alert_windows_notification_message, appName); Loading Loading @@ -134,16 +134,14 @@ class AlertWindowNotification { return PendingIntent.getActivity(context, mRequestCode, intent, FLAG_CANCEL_CURRENT); } private void createNotificationChannelIfNeeded(Context context, String appName) { if (mNotificationManager.getNotificationChannel(mNotificationTag) != null) { return; } private void createNotificationChannel(Context context, String appName) { final String nameChannel = context.getString(R.string.alert_windows_notification_channel_name, appName); final NotificationChannel channel = new NotificationChannel(mNotificationTag, nameChannel, IMPORTANCE_MIN); channel.enableLights(false); channel.enableVibration(false); channel.setBlockableSystem(true); mNotificationManager.createNotificationChannel(channel); } Loading