diff options
2 files changed, 80 insertions, 4 deletions
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index bcc201989bc6..f45c4a94e276 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -6243,6 +6243,7 @@ public class NotificationManagerService extends SystemService { int callingUid = Binder.getCallingUid(); @ZenModeConfig.ConfigOrigin int origin = computeZenOrigin(fromUser); + boolean isSystemCaller = isCallerSystemOrSystemUiOrShell(); boolean shouldApplyAsImplicitRule = android.app.Flags.modesApi() && !canManageGlobalZenPolicy(pkg, callingUid); @@ -6279,11 +6280,33 @@ public class NotificationManagerService extends SystemService { policy.priorityCallSenders, policy.priorityMessageSenders, policy.suppressedVisualEffects, currPolicy.priorityConversationSenders); } + int newVisualEffects = calculateSuppressedVisualEffects( policy, currPolicy, applicationInfo.targetSdkVersion); - policy = new Policy(policy.priorityCategories, - policy.priorityCallSenders, policy.priorityMessageSenders, - newVisualEffects, policy.priorityConversationSenders); + + if (android.app.Flags.modesUi()) { + // 1. Callers should not modify STATE_CHANNELS_BYPASSING_DND, which is + // internally calculated and only indicates whether channels that want to bypass + // DND _exist_. + // 2. Only system callers should modify STATE_PRIORITY_CHANNELS_BLOCKED because + // it is @hide. + // 3. If the policy has been modified by the targetSdkVersion checks above then + // it has lost its state flags and that's fine (STATE_PRIORITY_CHANNELS_BLOCKED + // didn't exist until V). + int newState = Policy.STATE_UNSET; + if (isSystemCaller && policy.state != Policy.STATE_UNSET) { + newState = Policy.policyState( + currPolicy.hasPriorityChannels(), + policy.allowPriorityChannels()); + } + policy = new Policy(policy.priorityCategories, + policy.priorityCallSenders, policy.priorityMessageSenders, + newVisualEffects, newState, policy.priorityConversationSenders); + } else { + policy = new Policy(policy.priorityCategories, + policy.priorityCallSenders, policy.priorityMessageSenders, + newVisualEffects, policy.priorityConversationSenders); + } if (shouldApplyAsImplicitRule) { mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(pkg, callingUid, policy); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index d69d678746a6..93450c708f8f 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -193,6 +193,7 @@ import android.app.Notification.MessagingStyle.Message; import android.app.NotificationChannel; import android.app.NotificationChannelGroup; import android.app.NotificationManager; +import android.app.NotificationManager.Policy; import android.app.PendingIntent; import android.app.Person; import android.app.RemoteInput; @@ -655,7 +656,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mAtm.getTaskToShowPermissionDialogOn(anyString(), anyInt())) .thenReturn(INVALID_TASK_ID); mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class)); - when(mUm.getProfileIds(eq(mUserId), eq(false))).thenReturn(new int[] { mUserId }); + when(mUm.getProfileIds(eq(mUserId), anyBoolean())).thenReturn(new int[]{mUserId}); + when(mUmInternal.getProfileIds(eq(mUserId), anyBoolean())).thenReturn(new int[]{mUserId}); when(mAmi.getCurrentUserId()).thenReturn(mUserId); when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(true); @@ -15936,6 +15938,57 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertThat(updatedRule.getValue().isEnabled()).isFalse(); } + @Test + @EnableFlags({android.app.Flags.FLAG_MODES_API, android.app.Flags.FLAG_MODES_UI}) + public void setNotificationPolicy_fromSystemApp_appliesPriorityChannelsAllowed() + throws Exception { + setUpRealZenTest(); + // Start with hasPriorityChannels=true, allowPriorityChannels=true ("default"). + mService.mZenModeHelper.setNotificationPolicy(new Policy(0, 0, 0, 0, + Policy.policyState(true, true), 0), + ZenModeConfig.ORIGIN_SYSTEM, Process.SYSTEM_UID); + + // The caller will supply states with "wrong" hasPriorityChannels. + int stateBlockingPriorityChannels = Policy.policyState(false, false); + mBinderService.setNotificationPolicy(mPkg, + new Policy(1, 0, 0, 0, stateBlockingPriorityChannels, 0), false); + + // hasPriorityChannels is untouched and allowPriorityChannels was updated. + assertThat(mBinderService.getNotificationPolicy(mPkg).priorityCategories).isEqualTo(1); + assertThat(mBinderService.getNotificationPolicy(mPkg).state).isEqualTo( + Policy.policyState(true, false)); + + // Same but setting allowPriorityChannels to true. + int stateAllowingPriorityChannels = Policy.policyState(false, true); + mBinderService.setNotificationPolicy(mPkg, + new Policy(2, 0, 0, 0, stateAllowingPriorityChannels, 0), false); + + assertThat(mBinderService.getNotificationPolicy(mPkg).priorityCategories).isEqualTo(2); + assertThat(mBinderService.getNotificationPolicy(mPkg).state).isEqualTo( + Policy.policyState(true, true)); + } + + @Test + @EnableFlags({android.app.Flags.FLAG_MODES_API, android.app.Flags.FLAG_MODES_UI}) + @DisableCompatChanges(NotificationManagerService.MANAGE_GLOBAL_ZEN_VIA_IMPLICIT_RULES) + public void setNotificationPolicy_fromRegularAppThatCanModifyPolicy_ignoresState() + throws Exception { + setUpRealZenTest(); + // Start with hasPriorityChannels=true, allowPriorityChannels=true ("default"). + mService.mZenModeHelper.setNotificationPolicy(new Policy(0, 0, 0, 0, + Policy.policyState(true, true), 0), + ZenModeConfig.ORIGIN_SYSTEM, Process.SYSTEM_UID); + mService.setCallerIsNormalPackage(); + + mBinderService.setNotificationPolicy(mPkg, + new Policy(1, 0, 0, 0, Policy.policyState(false, false), 0), false); + + // Policy was updated but the attempt to change state was ignored (it's a @hide API). + assertThat(mBinderService.getNotificationPolicy(mPkg).priorityCategories).isEqualTo(1); + assertThat(mBinderService.getNotificationPolicy(mPkg).state).isEqualTo( + Policy.policyState(true, true)); + } + /** Prepares for a zen-related test that uses the real {@link ZenModeHelper}. */ private void setUpRealZenTest() throws Exception { when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt())) |