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

Commit 302bb839 authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Use shared flag

Test: post ongoing notification, look at its flags
Test: NotificationManagerServiceTest
Bug: 240553971
Change-Id: I8c5955339077f6d9486d7eaeaba69548a52fde4e
parent f58eb0b2
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ import static android.service.notification.NotificationListenerService.TRIM_FULL
import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
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.util.FrameworkStatsLog.DND_MODE_RULE;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES;
@@ -271,6 +272,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IAppOpsService;
import com.android.internal.compat.IPlatformCompat;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags;
import com.android.internal.logging.InstanceId;
import com.android.internal.logging.InstanceIdSequence;
import com.android.internal.logging.MetricsLogger;
@@ -577,11 +579,11 @@ public class NotificationManagerService extends SystemService {
    private float mInCallNotificationVolume;
    private Binder mCallNotificationToken = null;
    private static final boolean ONGOING_DISMISSAL = SystemProperties.getBoolean(
            "persist.sysui.notification.ongoing_dismissal", true);
    @VisibleForTesting
    protected boolean mSystemExemptFromDismissal = false;
    private SystemUiSystemPropertiesFlags.FlagResolver mFlagResolver;
    // used as a mutex for access to all active notifications & listeners
    final Object mNotificationLock = new Object();
    @GuardedBy("mNotificationLock")
@@ -1208,7 +1210,8 @@ public class NotificationManagerService extends SystemService {
                }
            }
            int mustNotHaveFlags = ONGOING_DISMISSAL ? FLAG_NO_DISMISS : FLAG_ONGOING_EVENT;
            int mustNotHaveFlags = mFlagResolver.isEnabled(ALLOW_DISMISS_ONGOING)
                    ? FLAG_NO_DISMISS : FLAG_ONGOING_EVENT;
            cancelNotification(callingUid, callingPid, pkg, tag, id,
                    /* mustHaveFlags= */ 0,
                    /* mustNotHaveFlags= */ mustNotHaveFlags,
@@ -2219,7 +2222,8 @@ public class NotificationManagerService extends SystemService {
            TelephonyManager telephonyManager, ActivityManagerInternal ami,
            MultiRateLimiter toastRateLimiter, PermissionHelper permissionHelper,
            UsageStatsManagerInternal usageStatsManagerInternal,
            TelecomManager telecomManager, NotificationChannelLogger channelLogger) {
            TelecomManager telecomManager, NotificationChannelLogger channelLogger,
            SystemUiSystemPropertiesFlags.FlagResolver flagResolver) {
        mHandler = handler;
        Resources resources = getContext().getResources();
        mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
@@ -2417,6 +2421,8 @@ public class NotificationManagerService extends SystemService {
        mMsgPkgsAllowedAsConvos = Set.of(getStringArrayResource(
                com.android.internal.R.array.config_notificationMsgPkgsAllowedAsConvos));
        mFlagResolver = flagResolver;
        mStatsManager = statsManager;
        mToastRateLimiter = toastRateLimiter;
@@ -2548,7 +2554,7 @@ public class NotificationManagerService extends SystemService {
                        AppGlobals.getPermissionManager()),
                LocalServices.getService(UsageStatsManagerInternal.class),
                getContext().getSystemService(TelecomManager.class),
                new NotificationChannelLoggerImpl());
                new NotificationChannelLoggerImpl(), SystemUiSystemPropertiesFlags.getResolver());
        publishBinderService(Context.NOTIFICATION_SERVICE, mService, /* allowIsolated= */ false,
                DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL);
@@ -6702,7 +6708,7 @@ public class NotificationManagerService extends SystemService {
        Notification.addFieldsFromContext(ai, notification);
        // Only notifications that can be non-dismissible can have the flag FLAG_NO_DISMISS
        if (ONGOING_DISMISSAL) {
        if (mFlagResolver.isEnabled(ALLOW_DISMISS_ONGOING)) {
            if (((notification.flags & FLAG_ONGOING_EVENT) > 0)
                    && canBeNonDismissible(ai, notification)) {
                notification.flags |= FLAG_NO_DISMISS;
+30 −61
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ import static android.service.notification.NotificationListenerService.Ranking.U
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
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.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;

import static com.google.common.truth.Truth.assertThat;
@@ -202,6 +203,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;
import com.android.internal.logging.InstanceIdSequence;
import com.android.internal.logging.InstanceIdSequenceFake;
import com.android.internal.messages.nano.SystemMessageProto;
@@ -374,6 +376,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
    BroadcastReceiver mPackageIntentReceiver;
    NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
    TestableNotificationManagerService.StrongAuthTrackerFake mStrongAuthTracker;

    TestFlagResolver mTestFlagResolver = new TestFlagResolver();

    private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
            1 << 30);
    @Mock
@@ -522,7 +527,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                mAppOpsManager, mAppOpsService, mUm, mHistoryManager, mStatsManager,
                mock(TelephonyManager.class),
                mAmi, mToastRateLimiter, mPermissionHelper, mock(UsageStatsManagerInternal.class),
                mTelecomManager, mLogger);
                mTelecomManager, mLogger, mTestFlagResolver);
        // Return first true for RoleObserver main-thread check
        when(mMainLooper.isCurrentThread()).thenReturn(true).thenReturn(false);
        mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY, mMainLooper);
@@ -10120,8 +10125,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
            throws Exception {
        // Given: a notification from an app on the system partition has the flag
        // FLAG_ONGOING_EVENT set
        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
        mService.setOngoingDismissal(true);
        // feature flag: ALLOW_DISMISS_ONGOING is on
        mTestFlagResolver.setFlagOverride(ALLOW_DISMISS_ONGOING, true);
        Notification n = new Notification.Builder(mContext, "test")
                .setOngoing(true)
                .build();
@@ -10136,17 +10141,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {

        // Then: the notification's flag FLAG_NO_DISMISS should be set
        assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);

        // Avoid affecting other tests
        mService.setOngoingDismissal(false);
    }

    @Test
    public void fixMediaNotification_withOnGoingFlag_shouldBeNonDismissible()
            throws Exception {
        // Given: a media notification has the flag FLAG_ONGOING_EVENT set
        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
        mService.setOngoingDismissal(true);
        // feature flag: ALLOW_DISMISS_ONGOING is on
        mTestFlagResolver.setFlagOverride(ALLOW_DISMISS_ONGOING, true);
        Notification n = new Notification.Builder(mContext, "test")
                .setOngoing(true)
                .setStyle(new Notification.MediaStyle()
@@ -10158,16 +10160,13 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {

        // Then: the notification's flag FLAG_NO_DISMISS should be set
        assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);

        // Avoid affecting other tests
        mService.setOngoingDismissal(false);
    }

    @Test
    public void fixNonExemptNotification_withOnGoingFlag_shouldBeDismissible() throws Exception {
        // Given: a non-exempt notification has the flag FLAG_ONGOING_EVENT set
        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
        mService.setOngoingDismissal(true);
        // feature flag: ALLOW_DISMISS_ONGOING is on
        mTestFlagResolver.setFlagOverride(ALLOW_DISMISS_ONGOING, true);
        Notification n = new Notification.Builder(mContext, "test")
                .setOngoing(true)
                .build();
@@ -10177,9 +10176,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {

        // Then: the notification's flag FLAG_NO_DISMISS should not be set
        assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);

        // Avoid affecting other tests
        mService.setOngoingDismissal(false);
    }

    @Test
@@ -10187,8 +10183,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
            throws Exception {
        // Given: a non-exempt notification has the flag FLAG_NO_DISMISS set (even though this is
        // not allowed)
        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
        mService.setOngoingDismissal(true);
        // feature flag: ALLOW_DISMISS_ONGOING is on
        mTestFlagResolver.setFlagOverride(ALLOW_DISMISS_ONGOING, true);
        Notification n = new Notification.Builder(mContext, "test")
                .build();
        n.flags |= Notification.FLAG_NO_DISMISS;
@@ -10198,17 +10194,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {

        // Then: the notification's flag FLAG_NO_DISMISS should be cleared
        assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);

        // Avoid affecting other tests
        mService.setOngoingDismissal(false);
    }

    @Test
    public void fixSystemNotification_withoutOnGoingFlag_shouldBeDismissible() throws Exception {
        // Given: a notification from an app on the system partition doesn't have the flag
        // FLAG_ONGOING_EVENT set
        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
        mService.setOngoingDismissal(true);
        // feature flag: ALLOW_DISMISS_ONGOING is on
        mTestFlagResolver.setFlagOverride(ALLOW_DISMISS_ONGOING, true);
        Notification n = new Notification.Builder(mContext, "test")
                .setOngoing(false)
                .build();
@@ -10223,9 +10216,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {

        // Then: the notification's flag FLAG_NO_DISMISS should not be set
        assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);

        // Avoid affecting other tests
        mService.setOngoingDismissal(false);
    }

    @Test
@@ -10233,8 +10223,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
            throws Exception {
        // Given: a notification from an app on the system partition doesn't have the flag
        // FLAG_ONGOING_EVENT set, but has the flag FLAG_NO_DISMISS set
        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
        mService.setOngoingDismissal(true);
        // feature flag: ALLOW_DISMISS_ONGOING is on
        mTestFlagResolver.setFlagOverride(ALLOW_DISMISS_ONGOING, true);
        Notification n = new Notification.Builder(mContext, "test")
                .setOngoing(false)
                .build();
@@ -10250,16 +10240,13 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {

        // Then: the notification's flag FLAG_NO_DISMISS should be cleared
        assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);

        // Avoid affecting other tests
        mService.setOngoingDismissal(false);
    }

    @Test
    public void fixMediaNotification_withoutOnGoingFlag_shouldBeDismissible() throws Exception {
        // Given: a media notification doesn't have the flag FLAG_ONGOING_EVENT set
        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
        mService.setOngoingDismissal(true);
        // feature flag: ALLOW_DISMISS_ONGOING is on
        mTestFlagResolver.setFlagOverride(ALLOW_DISMISS_ONGOING, true);
        Notification n = new Notification.Builder(mContext, "test")
                .setOngoing(false)
                .setStyle(new Notification.MediaStyle()
@@ -10271,9 +10258,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {

        // Then: the notification's flag FLAG_NO_DISMISS should not be set
        assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);

        // Avoid affecting other tests
        mService.setOngoingDismissal(false);
    }

    @Test
@@ -10281,8 +10265,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
            throws Exception {
        // Given: a media notification doesn't have the flag FLAG_ONGOING_EVENT set,
        // but has the flag FLAG_NO_DISMISS set
        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
        mService.setOngoingDismissal(true);
        // feature flag: ALLOW_DISMISS_ONGOING is on
        mTestFlagResolver.setFlagOverride(ALLOW_DISMISS_ONGOING, true);
        Notification n = new Notification.Builder(mContext, "test")
                .setOngoing(false)
                .setStyle(new Notification.MediaStyle()
@@ -10295,18 +10279,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {

        // Then: the notification's flag FLAG_NO_DISMISS should be cleared
        assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);

        // Avoid affecting other tests
        mService.setOngoingDismissal(false);
    }

    @Test
    public void fixNonExempt_Notification_withoutOnGoingFlag_shouldBeDismissible()
            throws Exception {
        // Given: a non-exempt notification has the flag FLAG_ONGOING_EVENT set
        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
        mService.setOngoingDismissal(true);
        mService.setOngoingDismissal(true);
        // feature flag: ALLOW_DISMISS_ONGOING is on
        mTestFlagResolver.setFlagOverride(ALLOW_DISMISS_ONGOING, true);
        Notification n = new Notification.Builder(mContext, "test")
                .setOngoing(false)
                .build();
@@ -10316,9 +10296,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {

        // Then: the notification's flag FLAG_NO_DISMISS should not be set
        assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);

        // Avoid affecting other tests
        mService.setOngoingDismissal(false);
    }

    @Test
@@ -10326,8 +10303,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
            throws Exception {
        when(mDevicePolicyManager.isActiveDeviceOwner(mUid)).thenReturn(true);
        // Given: a notification has the flag FLAG_ONGOING_EVENT set
        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
        mService.setOngoingDismissal(true);
        // feature flag: ALLOW_DISMISS_ONGOING is on
        mTestFlagResolver.setFlagOverride(ALLOW_DISMISS_ONGOING, true);
        mService.setSystemExemptFromDismissal(false);
        Notification n = new Notification.Builder(mContext, "test")
                .setOngoing(true)
@@ -10338,9 +10315,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {

        // Then: the notification's flag FLAG_NO_DISMISS should be set
        assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);

        // Avoid affecting other tests
        mService.setOngoingDismissal(false);
    }

    @Test
@@ -10350,8 +10324,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid,
                PKG)).thenReturn(AppOpsManager.MODE_ALLOWED);
        // Given: a notification has the flag FLAG_ONGOING_EVENT set
        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
        mService.setOngoingDismissal(true);
        // feature flag: ALLOW_DISMISS_ONGOING is on
        mTestFlagResolver.setFlagOverride(ALLOW_DISMISS_ONGOING, true);
        mService.setSystemExemptFromDismissal(true);
        Notification n = new Notification.Builder(mContext, "test")
                .setOngoing(true)
@@ -10363,8 +10337,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
        // Then: the notification's flag FLAG_NO_DISMISS should be set
        assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);

        // Avoid affecting other tests
        mService.setOngoingDismissal(false);
        mService.setSystemExemptFromDismissal(false);
    }

@@ -10375,8 +10347,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid,
                PKG)).thenReturn(AppOpsManager.MODE_ALLOWED);
        // Given: a notification has the flag FLAG_ONGOING_EVENT set
        // feature flag: NOTIFICATION_ONGOING_DISMISSAL is on
        mService.setOngoingDismissal(true);
        // feature flag: ALLOW_DISMISS_ONGOING is on
        mTestFlagResolver.setFlagOverride(ALLOW_DISMISS_ONGOING, true);
        mService.setSystemExemptFromDismissal(false);
        Notification n = new Notification.Builder(mContext, "test")
                .setOngoing(true)
@@ -10387,8 +10359,5 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {

        // Then: the notification's flag FLAG_NO_DISMISS should not be set
        assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);

        // Avoid affecting other tests
        mService.setOngoingDismissal(false);
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -168,7 +168,7 @@ public class RoleObserverTest extends UiServiceTestCase {
                    mock(ActivityManagerInternal.class),
                    mock(MultiRateLimiter.class), mock(PermissionHelper.class),
                    mock(UsageStatsManagerInternal.class), mock (TelecomManager.class),
                    mock(NotificationChannelLogger.class));
                    mock(NotificationChannelLogger.class), new TestFlagResolver());
        } catch (SecurityException e) {
            if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) {
                throw e;
+35 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.server.notification;

import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags;

import java.util.HashMap;
import java.util.Map;

public class TestFlagResolver implements SystemUiSystemPropertiesFlags.FlagResolver {
    private Map<SystemUiSystemPropertiesFlags.Flag, Boolean> mOverrides = new HashMap<>();

    @Override
    public boolean isEnabled(SystemUiSystemPropertiesFlags.Flag flag) {
        return mOverrides.getOrDefault(flag, flag.mDefaultValue);
    }

    public void setFlagOverride(SystemUiSystemPropertiesFlags.Flag flag, boolean isEnabled) {
        mOverrides.put(flag, isEnabled);
    }
}
+0 −7
Original line number Diff line number Diff line
@@ -36,8 +36,6 @@ public class TestableNotificationManagerService extends NotificationManagerServi
    int countLogSmartSuggestionsVisible = 0;
    Set<Integer> mChannelToastsSent = new HashSet<>();

    public boolean ONGOING_DISMISSAL = false;

    String stringArrayResourceValue;
    @Nullable
    NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
@@ -162,11 +160,6 @@ public class TestableNotificationManagerService extends NotificationManagerServi
        }
    }

    // Mock SystemProperties
    protected void setOngoingDismissal(boolean ongoingDismissal) {
        ONGOING_DISMISSAL = ongoingDismissal;
    }

    protected void setSystemExemptFromDismissal(boolean isOn) {
        mSystemExemptFromDismissal = isOn;
    }