diff options
| author | 2017-07-10 15:01:07 +0000 | |
|---|---|---|
| committer | 2017-07-10 15:01:07 +0000 | |
| commit | 330ca71a95f578abfcb2c33f7b331ab119a0b7d1 (patch) | |
| tree | db48bab9b620c9af9d59286daca1e4f6388ca905 | |
| parent | 34a537fea2a0151a6c8015f3d2b6ff26eeeaaeb9 (diff) | |
| parent | 4db5955557154e40838ad2e6bdf140069b0776f8 (diff) | |
Merge "Allow setup apps to colorize notifications."
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()); + } } |