summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2017-07-10 15:01:07 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2017-07-10 15:01:07 +0000
commit330ca71a95f578abfcb2c33f7b331ab119a0b7d1 (patch)
treedb48bab9b620c9af9d59286daca1e4f6388ca905
parent34a537fea2a0151a6c8015f3d2b6ff26eeeaaeb9 (diff)
parent4db5955557154e40838ad2e6bdf140069b0776f8 (diff)
Merge "Allow setup apps to colorize notifications."
-rw-r--r--core/java/android/app/Notification.java16
-rw-r--r--core/res/AndroidManifest.xml5
-rw-r--r--core/tests/coretests/src/android/app/NotificationTest.java47
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java10
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecord.java6
-rw-r--r--services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java29
6 files changed, 104 insertions, 9 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 5a08cf3724ab..71b159ea0f66 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -561,6 +561,11 @@ public class Notification implements Parcelable
@SystemApi
public static final int FLAG_AUTOGROUP_SUMMARY = 0x00000400;
+ /**
+ * @hide
+ */
+ public static final int FLAG_CAN_COLORIZE = 0x00000800;
+
public int flags;
/** @hide */
@@ -5174,7 +5179,16 @@ public class Notification implements Parcelable
if (isColorizedMedia()) {
return true;
}
- return extras.getBoolean(EXTRA_COLORIZED) && isForegroundService();
+ return extras.getBoolean(EXTRA_COLORIZED)
+ && (hasColorizedPermission() || isForegroundService());
+ }
+
+ /**
+ * Returns whether an app can colorize due to the android.permission.USE_COLORIZED_NOTIFICATIONS
+ * permission. The permission is checked when a notification is enqueued.
+ */
+ private boolean hasColorizedPermission() {
+ return (flags & Notification.FLAG_CAN_COLORIZE) != 0;
}
/**
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a3cb35036dcd..55b57e933098 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3215,6 +3215,11 @@
<permission android:name="android.permission.MANAGE_NOTIFICATIONS"
android:protectionLevel="signature" />
+ <!-- Allows notifications to be colorized
+ <p>Not for use by third-party applications. @hide -->
+ <permission android:name="android.permission.USE_COLORIZED_NOTIFICATIONS"
+ android:protectionLevel="signature|setup" />
+
<!-- Allows access to keyguard secure storage. Only allowed for system processes.
@hide -->
<permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index ac1ac195b725..bc41922b7df1 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -18,6 +18,7 @@ package android.app;
import static com.android.internal.util.NotificationColorUtil.satisfiesTextContrast;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.content.Context;
@@ -26,8 +27,6 @@ import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import com.android.internal.util.NotificationColorUtil;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -44,9 +43,51 @@ public class NotificationTest {
}
@Test
+ public void testColorizedByPermission() {
+ Notification n = new Notification.Builder(mContext, "test")
+ .setFlag(Notification.FLAG_CAN_COLORIZE, true)
+ .setColorized(true)
+ .build();
+ assertTrue(n.isColorized());
+
+ n = new Notification.Builder(mContext, "test")
+ .setFlag(Notification.FLAG_CAN_COLORIZE, true)
+ .build();
+ assertFalse(n.isColorized());
+
+ n = new Notification.Builder(mContext, "test")
+ .setFlag(Notification.FLAG_CAN_COLORIZE, false)
+ .setColorized(true)
+ .build();
+ assertFalse(n.isColorized());
+ }
+
+ @Test
+ public void testColorizedByForeground() {
+ Notification n = new Notification.Builder(mContext, "test")
+ .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
+ .setColorized(true)
+ .build();
+ assertTrue(n.isColorized());
+
+ n = new Notification.Builder(mContext, "test")
+ .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
+ .build();
+ assertFalse(n.isColorized());
+
+ n = new Notification.Builder(mContext, "test")
+ .setFlag(Notification.FLAG_FOREGROUND_SERVICE, false)
+ .setColorized(true)
+ .build();
+ assertFalse(n.isColorized());
+ }
+
+ @Test
public void testColorSatisfiedWhenBgDarkTextDarker() {
Notification.Builder builder = getMediaNotification();
- builder.build();
+ Notification n = builder.build();
+
+ assertTrue(n.isColorized());
// An initial guess where the foreground color is actually darker than an already dark bg
int backgroundColor = 0xff585868;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 4690d649f272..448fa3326c98 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -20,6 +20,7 @@ import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
import static android.content.pm.PackageManager.FEATURE_TELEVISION;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.service.notification.NotificationListenerService
.NOTIFICATION_CHANNEL_OR_GROUP_ADDED;
import static android.service.notification.NotificationListenerService
@@ -3359,6 +3360,15 @@ public class NotificationManagerService extends SystemService {
pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
(userId == UserHandle.USER_ALL) ? UserHandle.USER_SYSTEM : userId);
Notification.addFieldsFromContext(ai, notification);
+
+ int canColorize = mPackageManagerClient.checkPermission(
+ android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, pkg);
+ if (canColorize == PERMISSION_GRANTED) {
+ notification.flags |= Notification.FLAG_CAN_COLORIZE;
+ } else {
+ notification.flags &= ~Notification.FLAG_CAN_COLORIZE;
+ }
+
} catch (NameNotFoundException e) {
Slog.e(TAG, "Cannot create a context for sending app", e);
return;
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 6953ffddaf33..1dee71cf2a5b 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -386,6 +386,7 @@ public final class NotificationRecord {
prefix = prefix + " ";
pw.println(prefix + "uid=" + sbn.getUid() + " userId=" + sbn.getUserId());
pw.println(prefix + "icon=" + iconStr);
+ pw.println(prefix + "flags=0x" + Integer.toHexString(notification.flags));
pw.println(prefix + "pri=" + notification.priority);
pw.println(prefix + "key=" + sbn.getKey());
pw.println(prefix + "seen=" + mIsSeen);
@@ -495,6 +496,7 @@ public final class NotificationRecord {
pw.println(prefix + "mAttributes= " + mAttributes);
pw.println(prefix + "mLight= " + mLight);
pw.println(prefix + "mShowBadge=" + mShowBadge);
+ pw.println(prefix + "mColorized=" + notification.isColorized());
pw.println(prefix + "effectiveNotificationChannel=" + getChannel());
if (getPeopleOverride() != null) {
pw.println(prefix + "overridePeople= " + TextUtils.join(",", getPeopleOverride()));
@@ -530,10 +532,10 @@ public final class NotificationRecord {
public final String toString() {
return String.format(
"NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s importance=%d key=%s" +
- " channel=%s: %s)",
+ ": %s)",
System.identityHashCode(this),
this.sbn.getPackageName(), this.sbn.getUser(), this.sbn.getId(),
- this.sbn.getTag(), this.mImportance, this.sbn.getKey(), this.getChannel().getId(),
+ this.sbn.getTag(), this.mImportance, this.sbn.getKey(),
this.sbn.getNotification());
}
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index 63cf024d4efd..b875b26d023f 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -18,7 +18,7 @@ package com.android.server.notification;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_NONE;
-import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
+import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -317,7 +317,7 @@ public class NotificationManagerServiceTest extends NotificationTestCase {
NotificationChannel channel = new NotificationChannel("id", "name",
NotificationManager.IMPORTANCE_HIGH);
- channel.setImportance(NotificationManager.IMPORTANCE_NONE);
+ channel.setImportance(IMPORTANCE_NONE);
NotificationRecord r = generateNotificationRecord(channel);
assertTrue(mNotificationManagerService.isBlocked(r, mUsageStats));
verify(mUsageStats, times(1)).registerBlocked(eq(r));
@@ -1207,7 +1207,8 @@ public class NotificationManagerServiceTest extends NotificationTestCase {
@Test
public void testOnlyAutogroupIfGroupChanged_noGroupChanged_autogroups()
throws Exception {
- NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group", false);
+ NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group",
+ false);
mNotificationManagerService.addNotification(r);
mNotificationManagerService.addEnqueuedNotification(r);
@@ -1219,4 +1220,26 @@ public class NotificationManagerServiceTest extends NotificationTestCase {
verify(mGroupHelper, never()).onNotificationPosted(any());
}
+ @Test
+ public void testNoFakeColorizedPermission() throws Exception {
+ when(mPackageManagerClient.checkPermission(any(), any())).thenReturn(PERMISSION_DENIED);
+ Notification.Builder nb = new Notification.Builder(mContext,
+ mTestNotificationChannel.getId())
+ .setContentTitle("foo")
+ .setColorized(true)
+ .setFlag(Notification.FLAG_CAN_COLORIZE, true)
+ .setSmallIcon(android.R.drawable.sym_def_app_icon);
+ StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", uid, 0,
+ nb.build(), new UserHandle(uid), null, 0);
+ NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
+
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
+ nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
+ waitForIdle();
+
+ NotificationRecord posted = mNotificationManagerService.findNotificationLocked(
+ PKG, null, nr.sbn.getId(), nr.sbn.getUserId());
+
+ assertFalse(posted.getNotification().isColorized());
+ }
}