Loading api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -160,6 +160,7 @@ package android { field public static final java.lang.String MOUNT_UNMOUNT_FILESYSTEMS = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS"; field public static final java.lang.String MOVE_PACKAGE = "android.permission.MOVE_PACKAGE"; field public static final java.lang.String NFC = "android.permission.NFC"; field public static final java.lang.String NOTIFICATION_DURING_SETUP = "android.permission.NOTIFICATION_DURING_SETUP"; field public static final java.lang.String OVERRIDE_WIFI_CONFIG = "android.permission.OVERRIDE_WIFI_CONFIG"; field public static final java.lang.String PACKAGE_USAGE_STATS = "android.permission.PACKAGE_USAGE_STATS"; field public static final java.lang.String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT"; core/res/AndroidManifest.xml +5 −0 Original line number Diff line number Diff line Loading @@ -3291,6 +3291,11 @@ <permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" android:protectionLevel="signature|privileged" /> <!-- @SystemApi Allows an application to show notifications before the device is provisioned. @hide <p>Not for use by third-party applications.</p> --> <permission android:name="android.permission.NOTIFICATION_DURING_SETUP" android:protectionLevel="signature|privileged" /> <!-- @SystemApi Allows an application to manage auto-fill sessions. @hide <p>Not for use by third-party applications.</p> --> <permission android:name="android.permission.MANAGE_AUTO_FILL" Loading packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java +26 −3 Original line number Diff line number Diff line Loading @@ -16,11 +16,15 @@ package com.android.systemui.statusbar; import android.app.AppGlobals; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.Context; import android.graphics.drawable.Icon; import android.os.RemoteException; import android.os.SystemClock; import android.service.notification.NotificationListenerService; import android.service.notification.NotificationListenerService.Ranking; Loading @@ -31,7 +35,9 @@ import android.util.ArrayMap; import android.view.View; import android.widget.ImageView; import android.widget.RemoteViews; import android.Manifest; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.StatusBarIcon; import com.android.internal.util.NotificationColorUtil; import com.android.systemui.statusbar.notification.InflationException; Loading Loading @@ -453,13 +459,30 @@ public class NotificationData { } // Q: What kinds of notifications should show during setup? // A: Almost none! Only things coming from the system (package is "android") that also // have special "kind" tags marking them as relevant for setup (see below). // A: Almost none! Only things coming from packages with permission // android.permission.NOTIFICATION_DURING_SETUP that also have special "kind" tags marking them // as relevant for setup (see below). public static boolean showNotificationEvenIfUnprovisioned(StatusBarNotification sbn) { return "android".equals(sbn.getPackageName()) return showNotificationEvenIfUnprovisioned(AppGlobals.getPackageManager(), sbn); } @VisibleForTesting static boolean showNotificationEvenIfUnprovisioned(IPackageManager packageManager, StatusBarNotification sbn) { return checkUidPermission(packageManager, Manifest.permission.NOTIFICATION_DURING_SETUP, sbn.getUid()) == PackageManager.PERMISSION_GRANTED && sbn.getNotification().extras.getBoolean(Notification.EXTRA_ALLOW_DURING_SETUP); } private static int checkUidPermission(IPackageManager packageManager, String permission, int uid) { try { return packageManager.checkUidPermission(permission, uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } public void dump(PrintWriter pw, String indent) { int N = mSortedAndFiltered.size(); pw.print(indent); Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java 0 → 100644 +110 −0 Original line number Diff line number Diff line /* * 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.systemui.statusbar; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.Manifest; import android.app.Notification; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.os.Bundle; import android.service.notification.StatusBarNotification; import android.support.test.annotation.UiThreadTest; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import com.android.systemui.SysuiTestCase; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @SmallTest @RunWith(AndroidJUnit4.class) public class NotificationDataTest extends SysuiTestCase { private static final int UID_NORMAL = 123; private static final int UID_ALLOW_DURING_SETUP = 456; private final StatusBarNotification mMockStatusBarNotification = mock(StatusBarNotification.class); private final IPackageManager mMockPackageManager = mock(IPackageManager.class); @Before public void setUp() throws Exception { when(mMockStatusBarNotification.getUid()).thenReturn(UID_NORMAL); when(mMockPackageManager.checkUidPermission( eq(Manifest.permission.NOTIFICATION_DURING_SETUP), eq(UID_NORMAL))) .thenReturn(PackageManager.PERMISSION_DENIED); when(mMockPackageManager.checkUidPermission( eq(Manifest.permission.NOTIFICATION_DURING_SETUP), eq(UID_ALLOW_DURING_SETUP))) .thenReturn(PackageManager.PERMISSION_GRANTED); } @Test @UiThreadTest public void testShowNotificationEvenIfUnprovisioned_FalseIfNoExtra() { initStatusBarNotification(false); when(mMockStatusBarNotification.getUid()).thenReturn(UID_ALLOW_DURING_SETUP); assertFalse( NotificationData.showNotificationEvenIfUnprovisioned( mMockPackageManager, mMockStatusBarNotification)); } @Test @UiThreadTest public void testShowNotificationEvenIfUnprovisioned_FalseIfNoPermission() { initStatusBarNotification(true); assertFalse( NotificationData.showNotificationEvenIfUnprovisioned( mMockPackageManager, mMockStatusBarNotification)); } @Test @UiThreadTest public void testShowNotificationEvenIfUnprovisioned_TrueIfHasPermissionAndExtra() { initStatusBarNotification(true); when(mMockStatusBarNotification.getUid()).thenReturn(UID_ALLOW_DURING_SETUP); assertTrue( NotificationData.showNotificationEvenIfUnprovisioned( mMockPackageManager, mMockStatusBarNotification)); } private void initStatusBarNotification(boolean allowDuringSetup) { Bundle bundle = new Bundle(); bundle.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, allowDuringSetup); Notification notification = new Notification.Builder(mContext, "test") .addExtras(bundle) .build(); when(mMockStatusBarNotification.getNotification()).thenReturn(notification); } } Loading
api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -160,6 +160,7 @@ package android { field public static final java.lang.String MOUNT_UNMOUNT_FILESYSTEMS = "android.permission.MOUNT_UNMOUNT_FILESYSTEMS"; field public static final java.lang.String MOVE_PACKAGE = "android.permission.MOVE_PACKAGE"; field public static final java.lang.String NFC = "android.permission.NFC"; field public static final java.lang.String NOTIFICATION_DURING_SETUP = "android.permission.NOTIFICATION_DURING_SETUP"; field public static final java.lang.String OVERRIDE_WIFI_CONFIG = "android.permission.OVERRIDE_WIFI_CONFIG"; field public static final java.lang.String PACKAGE_USAGE_STATS = "android.permission.PACKAGE_USAGE_STATS"; field public static final java.lang.String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT";
core/res/AndroidManifest.xml +5 −0 Original line number Diff line number Diff line Loading @@ -3291,6 +3291,11 @@ <permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" android:protectionLevel="signature|privileged" /> <!-- @SystemApi Allows an application to show notifications before the device is provisioned. @hide <p>Not for use by third-party applications.</p> --> <permission android:name="android.permission.NOTIFICATION_DURING_SETUP" android:protectionLevel="signature|privileged" /> <!-- @SystemApi Allows an application to manage auto-fill sessions. @hide <p>Not for use by third-party applications.</p> --> <permission android:name="android.permission.MANAGE_AUTO_FILL" Loading
packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java +26 −3 Original line number Diff line number Diff line Loading @@ -16,11 +16,15 @@ package com.android.systemui.statusbar; import android.app.AppGlobals; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.Context; import android.graphics.drawable.Icon; import android.os.RemoteException; import android.os.SystemClock; import android.service.notification.NotificationListenerService; import android.service.notification.NotificationListenerService.Ranking; Loading @@ -31,7 +35,9 @@ import android.util.ArrayMap; import android.view.View; import android.widget.ImageView; import android.widget.RemoteViews; import android.Manifest; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.StatusBarIcon; import com.android.internal.util.NotificationColorUtil; import com.android.systemui.statusbar.notification.InflationException; Loading Loading @@ -453,13 +459,30 @@ public class NotificationData { } // Q: What kinds of notifications should show during setup? // A: Almost none! Only things coming from the system (package is "android") that also // have special "kind" tags marking them as relevant for setup (see below). // A: Almost none! Only things coming from packages with permission // android.permission.NOTIFICATION_DURING_SETUP that also have special "kind" tags marking them // as relevant for setup (see below). public static boolean showNotificationEvenIfUnprovisioned(StatusBarNotification sbn) { return "android".equals(sbn.getPackageName()) return showNotificationEvenIfUnprovisioned(AppGlobals.getPackageManager(), sbn); } @VisibleForTesting static boolean showNotificationEvenIfUnprovisioned(IPackageManager packageManager, StatusBarNotification sbn) { return checkUidPermission(packageManager, Manifest.permission.NOTIFICATION_DURING_SETUP, sbn.getUid()) == PackageManager.PERMISSION_GRANTED && sbn.getNotification().extras.getBoolean(Notification.EXTRA_ALLOW_DURING_SETUP); } private static int checkUidPermission(IPackageManager packageManager, String permission, int uid) { try { return packageManager.checkUidPermission(permission, uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } public void dump(PrintWriter pw, String indent) { int N = mSortedAndFiltered.size(); pw.print(indent); Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java 0 → 100644 +110 −0 Original line number Diff line number Diff line /* * 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.systemui.statusbar; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.Manifest; import android.app.Notification; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.os.Bundle; import android.service.notification.StatusBarNotification; import android.support.test.annotation.UiThreadTest; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import com.android.systemui.SysuiTestCase; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @SmallTest @RunWith(AndroidJUnit4.class) public class NotificationDataTest extends SysuiTestCase { private static final int UID_NORMAL = 123; private static final int UID_ALLOW_DURING_SETUP = 456; private final StatusBarNotification mMockStatusBarNotification = mock(StatusBarNotification.class); private final IPackageManager mMockPackageManager = mock(IPackageManager.class); @Before public void setUp() throws Exception { when(mMockStatusBarNotification.getUid()).thenReturn(UID_NORMAL); when(mMockPackageManager.checkUidPermission( eq(Manifest.permission.NOTIFICATION_DURING_SETUP), eq(UID_NORMAL))) .thenReturn(PackageManager.PERMISSION_DENIED); when(mMockPackageManager.checkUidPermission( eq(Manifest.permission.NOTIFICATION_DURING_SETUP), eq(UID_ALLOW_DURING_SETUP))) .thenReturn(PackageManager.PERMISSION_GRANTED); } @Test @UiThreadTest public void testShowNotificationEvenIfUnprovisioned_FalseIfNoExtra() { initStatusBarNotification(false); when(mMockStatusBarNotification.getUid()).thenReturn(UID_ALLOW_DURING_SETUP); assertFalse( NotificationData.showNotificationEvenIfUnprovisioned( mMockPackageManager, mMockStatusBarNotification)); } @Test @UiThreadTest public void testShowNotificationEvenIfUnprovisioned_FalseIfNoPermission() { initStatusBarNotification(true); assertFalse( NotificationData.showNotificationEvenIfUnprovisioned( mMockPackageManager, mMockStatusBarNotification)); } @Test @UiThreadTest public void testShowNotificationEvenIfUnprovisioned_TrueIfHasPermissionAndExtra() { initStatusBarNotification(true); when(mMockStatusBarNotification.getUid()).thenReturn(UID_ALLOW_DURING_SETUP); assertTrue( NotificationData.showNotificationEvenIfUnprovisioned( mMockPackageManager, mMockStatusBarNotification)); } private void initStatusBarNotification(boolean allowDuringSetup) { Bundle bundle = new Bundle(); bundle.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, allowDuringSetup); Notification notification = new Notification.Builder(mContext, "test") .addExtras(bundle) .build(); when(mMockStatusBarNotification.getNotification()).thenReturn(notification); } }