Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4db59555 authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Allow setup apps to colorize notifications.

Fixes: 63147379
Test: runtest systemui-notification, core tests
Change-Id: I2077a9fd563826d978d0dc01be89dd0bbc09eebf
parent d092b9bb
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -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;
    }

    /**
+5 −0
Original line number Diff line number Diff line
@@ -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"
+44 −3
Original line number Diff line number Diff line
@@ -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;
@@ -43,10 +42,52 @@ public class NotificationTest {
        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
    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;
+10 −0
Original line number Diff line number Diff line
@@ -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;
+4 −2
Original line number Diff line number Diff line
@@ -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());
    }

Loading