Merge "Allow setup apps to colorize notifications." into oc-dr1-dev
am: e4101089bb
Change-Id: I14f8f499ac62ed47d40ca9b2a7bff0c79120dcd7
This commit is contained in:
@@ -559,6 +559,11 @@ public class Notification implements Parcelable
|
|||||||
@SystemApi
|
@SystemApi
|
||||||
public static final int FLAG_AUTOGROUP_SUMMARY = 0x00000400;
|
public static final int FLAG_AUTOGROUP_SUMMARY = 0x00000400;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final int FLAG_CAN_COLORIZE = 0x00000800;
|
||||||
|
|
||||||
public int flags;
|
public int flags;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@@ -5150,7 +5155,16 @@ public class Notification implements Parcelable
|
|||||||
if (isColorizedMedia()) {
|
if (isColorizedMedia()) {
|
||||||
return true;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3193,6 +3193,11 @@
|
|||||||
<permission android:name="android.permission.MANAGE_NOTIFICATIONS"
|
<permission android:name="android.permission.MANAGE_NOTIFICATIONS"
|
||||||
android:protectionLevel="signature" />
|
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.
|
<!-- Allows access to keyguard secure storage. Only allowed for system processes.
|
||||||
@hide -->
|
@hide -->
|
||||||
<permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"
|
<permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package android.app;
|
|||||||
|
|
||||||
import static com.android.internal.util.NotificationColorUtil.satisfiesTextContrast;
|
import static com.android.internal.util.NotificationColorUtil.satisfiesTextContrast;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -26,8 +27,6 @@ import android.support.test.InstrumentationRegistry;
|
|||||||
import android.support.test.filters.SmallTest;
|
import android.support.test.filters.SmallTest;
|
||||||
import android.support.test.runner.AndroidJUnit4;
|
import android.support.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
import com.android.internal.util.NotificationColorUtil;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -43,10 +42,52 @@ public class NotificationTest {
|
|||||||
mContext = InstrumentationRegistry.getContext();
|
mContext = InstrumentationRegistry.getContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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
|
@Test
|
||||||
public void testColorSatisfiedWhenBgDarkTextDarker() {
|
public void testColorSatisfiedWhenBgDarkTextDarker() {
|
||||||
Notification.Builder builder = getMediaNotification();
|
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
|
// An initial guess where the foreground color is actually darker than an already dark bg
|
||||||
int backgroundColor = 0xff585868;
|
int backgroundColor = 0xff585868;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static android.app.NotificationManager.IMPORTANCE_MIN;
|
|||||||
import static android.app.NotificationManager.IMPORTANCE_NONE;
|
import static android.app.NotificationManager.IMPORTANCE_NONE;
|
||||||
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
|
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
|
||||||
import static android.content.pm.PackageManager.FEATURE_TELEVISION;
|
import static android.content.pm.PackageManager.FEATURE_TELEVISION;
|
||||||
|
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||||
import static android.service.notification.NotificationListenerService
|
import static android.service.notification.NotificationListenerService
|
||||||
.NOTIFICATION_CHANNEL_OR_GROUP_ADDED;
|
.NOTIFICATION_CHANNEL_OR_GROUP_ADDED;
|
||||||
import static android.service.notification.NotificationListenerService
|
import static android.service.notification.NotificationListenerService
|
||||||
@@ -3174,6 +3175,15 @@ public class NotificationManagerService extends SystemService {
|
|||||||
pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
|
pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
|
||||||
(userId == UserHandle.USER_ALL) ? UserHandle.USER_SYSTEM : userId);
|
(userId == UserHandle.USER_ALL) ? UserHandle.USER_SYSTEM : userId);
|
||||||
Notification.addFieldsFromContext(ai, notification);
|
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) {
|
} catch (NameNotFoundException e) {
|
||||||
Slog.e(TAG, "Cannot create a context for sending app", e);
|
Slog.e(TAG, "Cannot create a context for sending app", e);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -386,6 +386,7 @@ public final class NotificationRecord {
|
|||||||
prefix = prefix + " ";
|
prefix = prefix + " ";
|
||||||
pw.println(prefix + "uid=" + sbn.getUid() + " userId=" + sbn.getUserId());
|
pw.println(prefix + "uid=" + sbn.getUid() + " userId=" + sbn.getUserId());
|
||||||
pw.println(prefix + "icon=" + iconStr);
|
pw.println(prefix + "icon=" + iconStr);
|
||||||
|
pw.println(prefix + "flags=0x" + Integer.toHexString(notification.flags));
|
||||||
pw.println(prefix + "pri=" + notification.priority);
|
pw.println(prefix + "pri=" + notification.priority);
|
||||||
pw.println(prefix + "key=" + sbn.getKey());
|
pw.println(prefix + "key=" + sbn.getKey());
|
||||||
pw.println(prefix + "seen=" + mIsSeen);
|
pw.println(prefix + "seen=" + mIsSeen);
|
||||||
@@ -495,6 +496,7 @@ public final class NotificationRecord {
|
|||||||
pw.println(prefix + "mAttributes= " + mAttributes);
|
pw.println(prefix + "mAttributes= " + mAttributes);
|
||||||
pw.println(prefix + "mLight= " + mLight);
|
pw.println(prefix + "mLight= " + mLight);
|
||||||
pw.println(prefix + "mShowBadge=" + mShowBadge);
|
pw.println(prefix + "mShowBadge=" + mShowBadge);
|
||||||
|
pw.println(prefix + "mColorized=" + notification.isColorized());
|
||||||
pw.println(prefix + "effectiveNotificationChannel=" + getChannel());
|
pw.println(prefix + "effectiveNotificationChannel=" + getChannel());
|
||||||
if (getPeopleOverride() != null) {
|
if (getPeopleOverride() != null) {
|
||||||
pw.println(prefix + "overridePeople= " + TextUtils.join(",", getPeopleOverride()));
|
pw.println(prefix + "overridePeople= " + TextUtils.join(",", getPeopleOverride()));
|
||||||
@@ -530,10 +532,10 @@ public final class NotificationRecord {
|
|||||||
public final String toString() {
|
public final String toString() {
|
||||||
return String.format(
|
return String.format(
|
||||||
"NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s importance=%d key=%s" +
|
"NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s importance=%d key=%s" +
|
||||||
" channel=%s: %s)",
|
": %s)",
|
||||||
System.identityHashCode(this),
|
System.identityHashCode(this),
|
||||||
this.sbn.getPackageName(), this.sbn.getUser(), this.sbn.getId(),
|
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());
|
this.sbn.getNotification());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.server.notification;
|
|||||||
|
|
||||||
import static android.app.NotificationManager.IMPORTANCE_LOW;
|
import static android.app.NotificationManager.IMPORTANCE_LOW;
|
||||||
import static android.app.NotificationManager.IMPORTANCE_NONE;
|
import static android.app.NotificationManager.IMPORTANCE_NONE;
|
||||||
|
import static android.content.pm.PackageManager.PERMISSION_DENIED;
|
||||||
|
|
||||||
import static junit.framework.Assert.assertEquals;
|
import static junit.framework.Assert.assertEquals;
|
||||||
import static junit.framework.Assert.assertFalse;
|
import static junit.framework.Assert.assertFalse;
|
||||||
@@ -951,4 +952,27 @@ public class NotificationManagerServiceTest extends NotificationTestCase {
|
|||||||
|
|
||||||
verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
|
verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user