Loading core/java/android/app/Notification.java +9 −0 Original line number Diff line number Diff line Loading @@ -712,6 +712,15 @@ public class Notification implements Parcelable */ public static final int FLAG_NO_DISMISS = 0x00002000; /** * Bit to be bitwise-ORed into the {@link #flags} field that should be * set by the system if the app that sent this notification does not have the permission to send * full screen intents. * * This flag is for internal use only; applications cannot set this flag directly. * @hide */ public static final int FLAG_FSI_REQUESTED_BUT_DENIED = 0x00004000; private static final List<Class<? extends Style>> PLATFORM_STYLE_CLASSES = Arrays.asList( BigTextStyle.class, BigPictureStyle.class, InboxStyle.class, MediaStyle.class, Loading services/core/java/com/android/server/notification/NotificationManagerService.java +54 −8 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static android.app.Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION import static android.app.Notification.FLAG_AUTOGROUP_SUMMARY; import static android.app.Notification.FLAG_BUBBLE; import static android.app.Notification.FLAG_FOREGROUND_SERVICE; import static android.app.Notification.FLAG_FSI_REQUESTED_BUT_DENIED; import static android.app.Notification.FLAG_INSISTENT; import static android.app.Notification.FLAG_NO_CLEAR; import static android.app.Notification.FLAG_NO_DISMISS; Loading Loading @@ -175,6 +176,7 @@ import android.companion.ICompanionDeviceManager; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; import android.compat.annotation.LoggingOnly; import android.content.AttributionSource; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentProvider; Loading Loading @@ -226,6 +228,8 @@ import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.os.VibrationEffect; import android.permission.PermissionCheckerManager; import android.permission.PermissionManager; import android.provider.DeviceConfig; import android.provider.Settings; import android.service.notification.Adjustment; Loading Loading @@ -528,6 +532,7 @@ public class NotificationManagerService extends SystemService { private IPackageManager mPackageManager; private PackageManager mPackageManagerClient; PackageManagerInternal mPackageManagerInternal; private PermissionManager mPermissionManager; private PermissionPolicyInternal mPermissionPolicyInternal; AudioManager mAudioManager; AudioManagerInternal mAudioManagerInternal; Loading Loading @@ -2226,7 +2231,8 @@ public class NotificationManagerService extends SystemService { MultiRateLimiter toastRateLimiter, PermissionHelper permissionHelper, UsageStatsManagerInternal usageStatsManagerInternal, TelecomManager telecomManager, NotificationChannelLogger channelLogger, SystemUiSystemPropertiesFlags.FlagResolver flagResolver) { SystemUiSystemPropertiesFlags.FlagResolver flagResolver, PermissionManager permissionManager) { mHandler = handler; Resources resources = getContext().getResources(); mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(), Loading @@ -2243,6 +2249,7 @@ public class NotificationManagerService extends SystemService { mPackageManager = packageManager; mPackageManagerClient = packageManagerClient; mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); mPermissionManager = permissionManager; mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class); mUmInternal = LocalServices.getService(UserManagerInternal.class); mUsageStatsManagerInternal = usageStatsManagerInternal; Loading Loading @@ -2557,7 +2564,8 @@ public class NotificationManagerService extends SystemService { AppGlobals.getPermissionManager()), LocalServices.getService(UsageStatsManagerInternal.class), getContext().getSystemService(TelecomManager.class), new NotificationChannelLoggerImpl(), SystemUiSystemPropertiesFlags.getResolver()); new NotificationChannelLoggerImpl(), SystemUiSystemPropertiesFlags.getResolver(), getContext().getSystemService(PermissionManager.class)); publishBinderService(Context.NOTIFICATION_SERVICE, mService, /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL); Loading Loading @@ -6666,10 +6674,21 @@ public class NotificationManagerService extends SystemService { handleSavePolicyFile(); } private void makeStickyHun(Notification notification) { notification.flags |= FLAG_FSI_REQUESTED_BUT_DENIED; if (notification.contentIntent == null) { // On notification click, if contentIntent is null, SystemUI launches the // fullScreenIntent instead. notification.contentIntent = notification.fullScreenIntent; } notification.fullScreenIntent = null; } @VisibleForTesting protected void fixNotification(Notification notification, String pkg, String tag, int id, @UserIdInt int userId, int notificationUid) throws NameNotFoundException, RemoteException { final ApplicationInfo ai = mPackageManagerClient.getApplicationInfoAsUser( pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING, (userId == UserHandle.USER_ALL) ? USER_SYSTEM : userId); Loading Loading @@ -6707,13 +6726,40 @@ public class NotificationManagerService extends SystemService { } } notification.flags &= ~FLAG_FSI_REQUESTED_BUT_DENIED; if (notification.fullScreenIntent != null && ai.targetSdkVersion >= Build.VERSION_CODES.Q) { final boolean forceDemoteFsiToStickyHun = mFlagResolver.isEnabled( SystemUiSystemPropertiesFlags.NotificationFlags.FSI_FORCE_DEMOTE); final boolean showStickyHunIfDenied = mFlagResolver.isEnabled( SystemUiSystemPropertiesFlags.NotificationFlags.SHOW_STICKY_HUN_FOR_DENIED_FSI); if (forceDemoteFsiToStickyHun) { makeStickyHun(notification); } else if (showStickyHunIfDenied) { final AttributionSource source = new AttributionSource.Builder(notificationUid) .setPackageName(pkg) .build(); final int permissionResult = mPermissionManager.checkPermissionForDataDelivery( Manifest.permission.USE_FULL_SCREEN_INTENT, source, /* message= */ null); if (permissionResult != PermissionCheckerManager.PERMISSION_GRANTED) { makeStickyHun(notification); } } else { int fullscreenIntentPermission = getContext().checkPermission( android.Manifest.permission.USE_FULL_SCREEN_INTENT, -1, notificationUid); if (fullscreenIntentPermission != PERMISSION_GRANTED) { notification.fullScreenIntent = null; Slog.w(TAG, "Package " + pkg + ": Use of fullScreenIntent requires the USE_FULL_SCREEN_INTENT permission"); Slog.w(TAG, "Package " + pkg + ": Use of fullScreenIntent requires the" + "USE_FULL_SCREEN_INTENT permission"); } } } Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +92 −1 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR; import static android.app.PendingIntent.FLAG_IMMUTABLE; import static android.app.PendingIntent.FLAG_MUTABLE; import static android.app.PendingIntent.FLAG_ONE_SHOT; Loading @@ -73,6 +74,8 @@ import static android.service.notification.NotificationListenerService.Ranking.U import static android.view.WindowManager.LayoutParams.TYPE_TOAST; import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.ALLOW_DISMISS_ONGOING; import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.FSI_FORCE_DEMOTE; import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.SHOW_STICKY_HUN_FOR_DENIED_FSI; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN; import static com.google.common.truth.Truth.assertThat; Loading @@ -82,6 +85,7 @@ import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNotSame; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertSame; import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.fail; Loading Loading @@ -111,6 +115,7 @@ import static org.mockito.Mockito.when; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; import android.Manifest; import android.annotation.SuppressLint; import android.app.ActivityManager; import android.app.ActivityManagerInternal; Loading Loading @@ -170,6 +175,8 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.permission.PermissionCheckerManager; import android.permission.PermissionManager; import android.provider.DeviceConfig; import android.provider.MediaStore; import android.provider.Settings; Loading Loading @@ -203,6 +210,7 @@ import androidx.test.InstrumentationRegistry; import com.android.internal.app.IAppOpsService; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.Flag; import com.android.internal.config.sysui.TestableFlagResolver; import com.android.internal.logging.InstanceIdSequence; import com.android.internal.logging.InstanceIdSequenceFake; Loading Loading @@ -320,6 +328,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Mock private NotificationManager mMockNm; @Mock private PermissionManager mPermissionManager; @Mock private DevicePolicyManagerInternal mDevicePolicyManager; @Mock Loading Loading @@ -527,7 +537,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mAppOpsManager, mAppOpsService, mUm, mHistoryManager, mStatsManager, mock(TelephonyManager.class), mAmi, mToastRateLimiter, mPermissionHelper, mock(UsageStatsManagerInternal.class), mTelecomManager, mLogger, mTestFlagResolver); mTelecomManager, mLogger, mTestFlagResolver, mPermissionManager); // Return first true for RoleObserver main-thread check when(mMainLooper.isCurrentThread()).thenReturn(true).thenReturn(false); mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper); Loading Loading @@ -604,6 +614,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID)); clearInvocations(mRankingHandler); when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); mTestFlagResolver.setFlagOverride(FSI_FORCE_DEMOTE, false); mTestFlagResolver.setFlagOverride(SHOW_STICKY_HUN_FOR_DENIED_FSI, false); } @After Loading Loading @@ -10111,6 +10124,84 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class)); } private void verifyStickyHun(Flag flag, int permissionState, boolean isSticky) throws Exception { mTestFlagResolver.setFlagOverride(flag, true); when(mPermissionManager.checkPermissionForDataDelivery( eq(Manifest.permission.USE_FULL_SCREEN_INTENT), any(), any())) .thenReturn(permissionState); Notification n = new Notification.Builder(mContext, "test") .setFullScreenIntent(mock(PendingIntent.class), true) .build(); mService.fixNotification(n, PKG, "tag", 9, 0, mUid); final int stickyFlag = n.flags & Notification.FLAG_FSI_REQUESTED_BUT_DENIED; if (isSticky) { assertNotSame(0, stickyFlag); } else { assertSame(0, stickyFlag); } } @Test public void testFixNotification_flagEnableStickyHun_fsiPermissionHardDenied_showStickyHun() throws Exception { verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI, /* permissionState= */ PermissionCheckerManager.PERMISSION_HARD_DENIED, /* isSticky= */ true); } @Test public void testFixNotification_flagEnableStickyHun_fsiPermissionSoftDenied_showStickyHun() throws Exception { verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI, /* permissionState= */ PermissionCheckerManager.PERMISSION_SOFT_DENIED, /* isSticky= */ true); } @Test public void testFixNotification_flagEnableStickyHun_fsiPermissionGranted_showFsi() throws Exception { verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI, /* permissionState= */ PermissionCheckerManager.PERMISSION_GRANTED, /* isSticky= */ false); } @Test public void testFixNotification_flagForceStickyHun_fsiPermissionHardDenied_showStickyHun() throws Exception { verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE, /* permissionState= */ PermissionCheckerManager.PERMISSION_HARD_DENIED, /* isSticky= */ true); } @Test public void testFixNotification_flagForceStickyHun_fsiPermissionSoftDenied_showStickyHun() throws Exception { verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE, /* permissionState= */ PermissionCheckerManager.PERMISSION_SOFT_DENIED, /* isSticky= */ true); } @Test public void testFixNotification_flagForceStickyHun_fsiPermissionGranted_showStickyHun() throws Exception { verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE, /* permissionState= */ PermissionCheckerManager.PERMISSION_GRANTED, /* isSticky= */ true); } @Test public void fixSystemNotification_withOnGoingFlag_shouldBeNonDismissible() throws Exception { Loading services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ import android.content.pm.PackageManager; import android.os.Looper; import android.os.UserHandle; import android.os.UserManager; import android.permission.PermissionManager; import android.telecom.TelecomManager; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; Loading Loading @@ -169,7 +170,8 @@ public class RoleObserverTest extends UiServiceTestCase { mock(ActivityManagerInternal.class), mock(MultiRateLimiter.class), mock(PermissionHelper.class), mock(UsageStatsManagerInternal.class), mock (TelecomManager.class), mock(NotificationChannelLogger.class), new TestableFlagResolver()); mock(NotificationChannelLogger.class), new TestableFlagResolver(), mock(PermissionManager.class)); } catch (SecurityException e) { if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) { throw e; Loading Loading
core/java/android/app/Notification.java +9 −0 Original line number Diff line number Diff line Loading @@ -712,6 +712,15 @@ public class Notification implements Parcelable */ public static final int FLAG_NO_DISMISS = 0x00002000; /** * Bit to be bitwise-ORed into the {@link #flags} field that should be * set by the system if the app that sent this notification does not have the permission to send * full screen intents. * * This flag is for internal use only; applications cannot set this flag directly. * @hide */ public static final int FLAG_FSI_REQUESTED_BUT_DENIED = 0x00004000; private static final List<Class<? extends Style>> PLATFORM_STYLE_CLASSES = Arrays.asList( BigTextStyle.class, BigPictureStyle.class, InboxStyle.class, MediaStyle.class, Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +54 −8 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static android.app.Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION import static android.app.Notification.FLAG_AUTOGROUP_SUMMARY; import static android.app.Notification.FLAG_BUBBLE; import static android.app.Notification.FLAG_FOREGROUND_SERVICE; import static android.app.Notification.FLAG_FSI_REQUESTED_BUT_DENIED; import static android.app.Notification.FLAG_INSISTENT; import static android.app.Notification.FLAG_NO_CLEAR; import static android.app.Notification.FLAG_NO_DISMISS; Loading Loading @@ -175,6 +176,7 @@ import android.companion.ICompanionDeviceManager; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; import android.compat.annotation.LoggingOnly; import android.content.AttributionSource; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentProvider; Loading Loading @@ -226,6 +228,8 @@ import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.os.VibrationEffect; import android.permission.PermissionCheckerManager; import android.permission.PermissionManager; import android.provider.DeviceConfig; import android.provider.Settings; import android.service.notification.Adjustment; Loading Loading @@ -528,6 +532,7 @@ public class NotificationManagerService extends SystemService { private IPackageManager mPackageManager; private PackageManager mPackageManagerClient; PackageManagerInternal mPackageManagerInternal; private PermissionManager mPermissionManager; private PermissionPolicyInternal mPermissionPolicyInternal; AudioManager mAudioManager; AudioManagerInternal mAudioManagerInternal; Loading Loading @@ -2226,7 +2231,8 @@ public class NotificationManagerService extends SystemService { MultiRateLimiter toastRateLimiter, PermissionHelper permissionHelper, UsageStatsManagerInternal usageStatsManagerInternal, TelecomManager telecomManager, NotificationChannelLogger channelLogger, SystemUiSystemPropertiesFlags.FlagResolver flagResolver) { SystemUiSystemPropertiesFlags.FlagResolver flagResolver, PermissionManager permissionManager) { mHandler = handler; Resources resources = getContext().getResources(); mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(), Loading @@ -2243,6 +2249,7 @@ public class NotificationManagerService extends SystemService { mPackageManager = packageManager; mPackageManagerClient = packageManagerClient; mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); mPermissionManager = permissionManager; mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class); mUmInternal = LocalServices.getService(UserManagerInternal.class); mUsageStatsManagerInternal = usageStatsManagerInternal; Loading Loading @@ -2557,7 +2564,8 @@ public class NotificationManagerService extends SystemService { AppGlobals.getPermissionManager()), LocalServices.getService(UsageStatsManagerInternal.class), getContext().getSystemService(TelecomManager.class), new NotificationChannelLoggerImpl(), SystemUiSystemPropertiesFlags.getResolver()); new NotificationChannelLoggerImpl(), SystemUiSystemPropertiesFlags.getResolver(), getContext().getSystemService(PermissionManager.class)); publishBinderService(Context.NOTIFICATION_SERVICE, mService, /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL); Loading Loading @@ -6666,10 +6674,21 @@ public class NotificationManagerService extends SystemService { handleSavePolicyFile(); } private void makeStickyHun(Notification notification) { notification.flags |= FLAG_FSI_REQUESTED_BUT_DENIED; if (notification.contentIntent == null) { // On notification click, if contentIntent is null, SystemUI launches the // fullScreenIntent instead. notification.contentIntent = notification.fullScreenIntent; } notification.fullScreenIntent = null; } @VisibleForTesting protected void fixNotification(Notification notification, String pkg, String tag, int id, @UserIdInt int userId, int notificationUid) throws NameNotFoundException, RemoteException { final ApplicationInfo ai = mPackageManagerClient.getApplicationInfoAsUser( pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING, (userId == UserHandle.USER_ALL) ? USER_SYSTEM : userId); Loading Loading @@ -6707,13 +6726,40 @@ public class NotificationManagerService extends SystemService { } } notification.flags &= ~FLAG_FSI_REQUESTED_BUT_DENIED; if (notification.fullScreenIntent != null && ai.targetSdkVersion >= Build.VERSION_CODES.Q) { final boolean forceDemoteFsiToStickyHun = mFlagResolver.isEnabled( SystemUiSystemPropertiesFlags.NotificationFlags.FSI_FORCE_DEMOTE); final boolean showStickyHunIfDenied = mFlagResolver.isEnabled( SystemUiSystemPropertiesFlags.NotificationFlags.SHOW_STICKY_HUN_FOR_DENIED_FSI); if (forceDemoteFsiToStickyHun) { makeStickyHun(notification); } else if (showStickyHunIfDenied) { final AttributionSource source = new AttributionSource.Builder(notificationUid) .setPackageName(pkg) .build(); final int permissionResult = mPermissionManager.checkPermissionForDataDelivery( Manifest.permission.USE_FULL_SCREEN_INTENT, source, /* message= */ null); if (permissionResult != PermissionCheckerManager.PERMISSION_GRANTED) { makeStickyHun(notification); } } else { int fullscreenIntentPermission = getContext().checkPermission( android.Manifest.permission.USE_FULL_SCREEN_INTENT, -1, notificationUid); if (fullscreenIntentPermission != PERMISSION_GRANTED) { notification.fullScreenIntent = null; Slog.w(TAG, "Package " + pkg + ": Use of fullScreenIntent requires the USE_FULL_SCREEN_INTENT permission"); Slog.w(TAG, "Package " + pkg + ": Use of fullScreenIntent requires the" + "USE_FULL_SCREEN_INTENT permission"); } } } Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +92 −1 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR; import static android.app.PendingIntent.FLAG_IMMUTABLE; import static android.app.PendingIntent.FLAG_MUTABLE; import static android.app.PendingIntent.FLAG_ONE_SHOT; Loading @@ -73,6 +74,8 @@ import static android.service.notification.NotificationListenerService.Ranking.U import static android.view.WindowManager.LayoutParams.TYPE_TOAST; import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.ALLOW_DISMISS_ONGOING; import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.FSI_FORCE_DEMOTE; import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.SHOW_STICKY_HUN_FOR_DENIED_FSI; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN; import static com.google.common.truth.Truth.assertThat; Loading @@ -82,6 +85,7 @@ import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNotSame; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertSame; import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.fail; Loading Loading @@ -111,6 +115,7 @@ import static org.mockito.Mockito.when; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; import android.Manifest; import android.annotation.SuppressLint; import android.app.ActivityManager; import android.app.ActivityManagerInternal; Loading Loading @@ -170,6 +175,8 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.permission.PermissionCheckerManager; import android.permission.PermissionManager; import android.provider.DeviceConfig; import android.provider.MediaStore; import android.provider.Settings; Loading Loading @@ -203,6 +210,7 @@ import androidx.test.InstrumentationRegistry; import com.android.internal.app.IAppOpsService; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.Flag; import com.android.internal.config.sysui.TestableFlagResolver; import com.android.internal.logging.InstanceIdSequence; import com.android.internal.logging.InstanceIdSequenceFake; Loading Loading @@ -320,6 +328,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Mock private NotificationManager mMockNm; @Mock private PermissionManager mPermissionManager; @Mock private DevicePolicyManagerInternal mDevicePolicyManager; @Mock Loading Loading @@ -527,7 +537,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mAppOpsManager, mAppOpsService, mUm, mHistoryManager, mStatsManager, mock(TelephonyManager.class), mAmi, mToastRateLimiter, mPermissionHelper, mock(UsageStatsManagerInternal.class), mTelecomManager, mLogger, mTestFlagResolver); mTelecomManager, mLogger, mTestFlagResolver, mPermissionManager); // Return first true for RoleObserver main-thread check when(mMainLooper.isCurrentThread()).thenReturn(true).thenReturn(false); mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper); Loading Loading @@ -604,6 +614,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID)); clearInvocations(mRankingHandler); when(mPermissionHelper.hasPermission(mUid)).thenReturn(true); mTestFlagResolver.setFlagOverride(FSI_FORCE_DEMOTE, false); mTestFlagResolver.setFlagOverride(SHOW_STICKY_HUN_FOR_DENIED_FSI, false); } @After Loading Loading @@ -10111,6 +10124,84 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { verify(mMockNm, never()).notify(anyString(), anyInt(), any(Notification.class)); } private void verifyStickyHun(Flag flag, int permissionState, boolean isSticky) throws Exception { mTestFlagResolver.setFlagOverride(flag, true); when(mPermissionManager.checkPermissionForDataDelivery( eq(Manifest.permission.USE_FULL_SCREEN_INTENT), any(), any())) .thenReturn(permissionState); Notification n = new Notification.Builder(mContext, "test") .setFullScreenIntent(mock(PendingIntent.class), true) .build(); mService.fixNotification(n, PKG, "tag", 9, 0, mUid); final int stickyFlag = n.flags & Notification.FLAG_FSI_REQUESTED_BUT_DENIED; if (isSticky) { assertNotSame(0, stickyFlag); } else { assertSame(0, stickyFlag); } } @Test public void testFixNotification_flagEnableStickyHun_fsiPermissionHardDenied_showStickyHun() throws Exception { verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI, /* permissionState= */ PermissionCheckerManager.PERMISSION_HARD_DENIED, /* isSticky= */ true); } @Test public void testFixNotification_flagEnableStickyHun_fsiPermissionSoftDenied_showStickyHun() throws Exception { verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI, /* permissionState= */ PermissionCheckerManager.PERMISSION_SOFT_DENIED, /* isSticky= */ true); } @Test public void testFixNotification_flagEnableStickyHun_fsiPermissionGranted_showFsi() throws Exception { verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI, /* permissionState= */ PermissionCheckerManager.PERMISSION_GRANTED, /* isSticky= */ false); } @Test public void testFixNotification_flagForceStickyHun_fsiPermissionHardDenied_showStickyHun() throws Exception { verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE, /* permissionState= */ PermissionCheckerManager.PERMISSION_HARD_DENIED, /* isSticky= */ true); } @Test public void testFixNotification_flagForceStickyHun_fsiPermissionSoftDenied_showStickyHun() throws Exception { verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE, /* permissionState= */ PermissionCheckerManager.PERMISSION_SOFT_DENIED, /* isSticky= */ true); } @Test public void testFixNotification_flagForceStickyHun_fsiPermissionGranted_showStickyHun() throws Exception { verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE, /* permissionState= */ PermissionCheckerManager.PERMISSION_GRANTED, /* isSticky= */ true); } @Test public void fixSystemNotification_withOnGoingFlag_shouldBeNonDismissible() throws Exception { Loading
services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java +3 −1 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ import android.content.pm.PackageManager; import android.os.Looper; import android.os.UserHandle; import android.os.UserManager; import android.permission.PermissionManager; import android.telecom.TelecomManager; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; Loading Loading @@ -169,7 +170,8 @@ public class RoleObserverTest extends UiServiceTestCase { mock(ActivityManagerInternal.class), mock(MultiRateLimiter.class), mock(PermissionHelper.class), mock(UsageStatsManagerInternal.class), mock (TelecomManager.class), mock(NotificationChannelLogger.class), new TestableFlagResolver()); mock(NotificationChannelLogger.class), new TestableFlagResolver(), mock(PermissionManager.class)); } catch (SecurityException e) { if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) { throw e; Loading