summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Julia Reynolds <juliacr@google.com> 2017-05-26 14:39:26 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2017-05-26 14:39:30 +0000
commit3a2ac3e11b336deb272e733dbdfc08317ce78b31 (patch)
treee4b709a12dfc5f6f468e964de1711a4fa3463d8a
parent03a243889c52cb24d2c80777f3da4653495357a3 (diff)
parentf732159cf8d6a4e1cd17542a3a2cf020ad6919a3 (diff)
Merge "Allow some system notifications to be blocked." into oc-dev
-rw-r--r--core/java/android/app/NotificationChannel.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java51
-rw-r--r--services/core/java/com/android/server/notification/RankingHelper.java3
-rw-r--r--services/core/java/com/android/server/wm/AlertWindowNotification.java8
-rw-r--r--services/tests/notification/src/com/android/server/notification/NotificationChannelTest.java53
6 files changed, 136 insertions, 9 deletions
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index bc7fcf55d0a3..c076e5e3c117 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -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 = ",";
/**
@@ -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.
@@ -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
@@ -249,6 +252,7 @@ public final class NotificationChannel implements Parcelable {
dest.writeInt(0);
}
dest.writeInt(mLightColor);
+ dest.writeBoolean(mBlockableSystem);
}
/**
@@ -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
/**
@@ -421,7 +431,6 @@ public final class NotificationChannel implements Parcelable {
this.mLockscreenVisibility = lockscreenVisibility;
}
-
/**
* Returns the id of this channel.
*/
@@ -549,6 +558,13 @@ public final class NotificationChannel implements Parcelable {
/**
* @hide
*/
+ public boolean isBlockableSystem() {
+ return mBlockableSystem;
+ }
+
+ /**
+ * @hide
+ */
@SystemApi
public void populateFromXml(XmlPullParser parser) {
// Name, id, and importance are set in the constructor.
@@ -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));
}
/**
@@ -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);
}
@@ -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;
}
@@ -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;
@@ -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;
}
@@ -824,6 +847,7 @@ public final class NotificationChannel implements Parcelable {
", mDeleted=" + mDeleted +
", mGroup='" + mGroup + '\'' +
", mAudioAttributes=" + mAudioAttributes +
+ ", mBlockableSystem=" + mBlockableSystem +
'}';
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index 7062216ad771..427708b02fbf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -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.
}
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 c7d5e68b93dd..638084763ea8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -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;
@@ -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";
@@ -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(
@@ -605,6 +615,45 @@ public class NotificationInfoTest extends SysuiTestCase {
}
@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);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 7a7bcede630e..4c3efce3be5c 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -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);
@@ -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();
diff --git a/services/core/java/com/android/server/wm/AlertWindowNotification.java b/services/core/java/com/android/server/wm/AlertWindowNotification.java
index 7ed3eac10d11..972623c9478d 100644
--- a/services/core/java/com/android/server/wm/AlertWindowNotification.java
+++ b/services/core/java/com/android/server/wm/AlertWindowNotification.java
@@ -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);
@@ -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);
}
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationChannelTest.java b/services/tests/notification/src/com/android/server/notification/NotificationChannelTest.java
new file mode 100644
index 000000000000..3007cb1755e2
--- /dev/null
+++ b/services/tests/notification/src/com/android/server/notification/NotificationChannelTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+
+import static junit.framework.Assert.assertEquals;
+
+import android.app.NotificationChannel;
+import android.os.Parcel;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NotificationChannelTest extends NotificationTestCase {
+
+ @Test
+ public void testWriteToParcel() {
+ NotificationChannel channel =
+ new NotificationChannel("1", "one", IMPORTANCE_DEFAULT);
+ Parcel parcel = Parcel.obtain();
+ channel.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ NotificationChannel channel1 = NotificationChannel.CREATOR.createFromParcel(parcel);
+ assertEquals(channel, channel1);
+ }
+
+ @Test
+ public void testSystemBlockable() {
+ NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT);
+ assertEquals(false, channel.isBlockableSystem());
+ channel.setBlockableSystem(true);
+ assertEquals(true, channel.isBlockableSystem());
+ }
+}