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

Commit 11624e75 authored by Garvit Narang's avatar Garvit Narang
Browse files

Fix setting device effects applier

Without this CL, setting a device effects applier causes the system to
crash. The applier is allowed to be set only once so if a system service
sets it via NotificationManagerInternal before NotificationManager
processes boot phases, a crash is observed at
PHASE_THIRD_PARTY_APPS_CAN_START because NM tries to set the default
device effects applier

Bug: 283030212
Test: atest ZenModeHelperTest
Flag: EXEMPT trivial
Change-Id: Ibbde8eca7748dcf31268853e957f7eac87956426
parent 6ce2ce16
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -82,6 +82,8 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BA
import static android.app.NotificationManager.zenModeFromInterruptionFilter;
import static android.app.StatusBarManager.ACTION_KEYGUARD_PRIVATE_NOTIFICATIONS_CHANGED;
import static android.app.StatusBarManager.EXTRA_KM_PRIVATE_NOTIFS_ALLOWED;
import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_CONFIG;
import static android.app.backup.NotificationLoggingConstants.ERROR_XML_PARSING;
import static android.content.Context.BIND_ALLOW_WHITELIST_MANAGEMENT;
import static android.content.Context.BIND_AUTO_CREATE;
import static android.content.Context.BIND_FOREGROUND_SERVICE;
@@ -162,8 +164,6 @@ import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.server.am.PendingIntentRecord.FLAG_ACTIVITY_SENDER;
import static com.android.server.am.PendingIntentRecord.FLAG_BROADCAST_SENDER;
import static com.android.server.am.PendingIntentRecord.FLAG_SERVICE_SENDER;
import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_CONFIG;
import static android.app.backup.NotificationLoggingConstants.ERROR_XML_PARSING;
import static com.android.server.notification.Flags.expireBitmaps;
import static com.android.server.policy.PhoneWindowManager.TOAST_WINDOW_ANIM_BUFFER;
import static com.android.server.policy.PhoneWindowManager.TOAST_WINDOW_TIMEOUT;
@@ -3069,7 +3069,7 @@ public class NotificationManagerService extends SystemService {
            migrateDefaultNAS();
            maybeShowInitialReviewPermissionsNotification();
            if (android.app.Flags.modesApi()) {
            if (android.app.Flags.modesApi() && !mZenModeHelper.hasDeviceEffectsApplier()) {
                // Cannot be done earlier, as some services aren't ready until this point.
                mZenModeHelper.setDeviceEffectsApplier(
                        new DefaultDeviceEffectsApplier(getContext()));
+11 −2
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ENABLED;
import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_REMOVED;
import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_UNKNOWN;
import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_CONFIG;
import static android.app.backup.NotificationLoggingConstants.ERROR_XML_PARSING;
import static android.service.notification.Condition.SOURCE_UNKNOWN;
import static android.service.notification.Condition.SOURCE_USER_ACTION;
import static android.service.notification.Condition.STATE_FALSE;
@@ -44,8 +46,6 @@ import static android.service.notification.ZenModeConfig.isImplicitRuleId;

import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
import static com.android.internal.util.Preconditions.checkArgument;
import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_CONFIG;
import static android.app.backup.NotificationLoggingConstants.ERROR_XML_PARSING;

import static java.util.Objects.requireNonNull;

@@ -302,6 +302,15 @@ public class ZenModeHelper {
        mIsSystemServicesReady = true;
    }

    /**
     * @return whether a {@link DeviceEffectsApplier} has already been set or not
     */
    boolean hasDeviceEffectsApplier() {
        synchronized (mConfigLock) {
            return mDeviceEffectsApplier != null;
        }
    }

    /**
     * Set the {@link DeviceEffectsApplier} used to apply the consolidated effects.
     *
+47 −19
Original line number Diff line number Diff line
@@ -43,8 +43,8 @@ import static android.app.Notification.FLAG_PROMOTED_ONGOING;
import static android.app.Notification.FLAG_USER_INITIATED_JOB;
import static android.app.Notification.GROUP_ALERT_CHILDREN;
import static android.app.Notification.VISIBILITY_PRIVATE;
import static android.app.NotificationChannel.NEWS_ID;
import static android.app.NotificationChannel.DEFAULT_CHANNEL_ID;
import static android.app.NotificationChannel.NEWS_ID;
import static android.app.NotificationChannel.PROMOTIONS_ID;
import static android.app.NotificationChannel.RECS_ID;
import static android.app.NotificationChannel.SOCIAL_MEDIA_ID;
@@ -78,7 +78,6 @@ import static android.app.PendingIntent.FLAG_ONE_SHOT;
import static android.app.StatusBarManager.ACTION_KEYGUARD_PRIVATE_NOTIFICATIONS_CHANGED;
import static android.app.StatusBarManager.EXTRA_KM_PRIVATE_NOTIFS_ALLOWED;
import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_CONFIG;
import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_RULES;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.PackageManager.FEATURE_TELECOM;
import static android.content.pm.PackageManager.FEATURE_WATCH;
@@ -336,12 +335,12 @@ import com.android.server.utils.quota.MultiRateLimiter;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.WindowManagerInternal;
import com.google.android.collect.Lists;
import com.google.common.collect.ImmutableList;
import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
import com.google.android.collect.Lists;
import com.google.common.collect.ImmutableList;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -360,13 +359,15 @@ import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
import platform.test.runner.parameterized.Parameters;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
@@ -375,9 +376,6 @@ import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
import platform.test.runner.parameterized.Parameters;
@SmallTest
@RunWith(ParameterizedAndroidJunit4.class)
@RunWithLooper
@@ -490,7 +488,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
    private final NotificationChannel mParentChannel =
            new NotificationChannel(PARENT_CHANNEL_ID, "parentName", IMPORTANCE_DEFAULT);
    private final NotificationChannel mConversationChannel =
            new NotificationChannel(CONVERSATION_CHANNEL_ID, "conversationName", IMPORTANCE_DEFAULT);
            new NotificationChannel(
                    CONVERSATION_CHANNEL_ID, "conversationName", IMPORTANCE_DEFAULT);
    private static final String PARENT_CHANNEL_ID = "parentChannelId";
    private static final String CONVERSATION_CHANNEL_ID = "conversationChannelId";
@@ -4262,8 +4261,13 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                    new NotificationChannel("foo", "foo", IMPORTANCE_HIGH));
        Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
        mBinderService.enqueueNotificationWithTag(mPkg, mPkg, "testTvExtenderChannelOverride_onTv", 0,
                generateNotificationRecord(null, tv).getNotification(), mUserId);
        mBinderService.enqueueNotificationWithTag(
                mPkg,
                mPkg,
                "testTvExtenderChannelOverride_onTv",
                0,
                generateNotificationRecord(null, tv).getNotification(),
                mUserId);
        verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
                anyString(), anyInt(), eq("foo"), eq(null), anyBoolean(), anyBoolean());
    }
@@ -4277,8 +4281,13 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                mTestNotificationChannel);
        Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
        mBinderService.enqueueNotificationWithTag(mPkg, mPkg, "testTvExtenderChannelOverride_notOnTv",
                0, generateNotificationRecord(null, tv).getNotification(), mUserId);
        mBinderService.enqueueNotificationWithTag(
                mPkg,
                mPkg,
                "testTvExtenderChannelOverride_notOnTv",
                0,
                generateNotificationRecord(null, tv).getNotification(),
                mUserId);
        verify(mPreferencesHelper, times(1)).getConversationNotificationChannel(
                anyString(), anyInt(), eq(mTestNotificationChannel.getId()), eq(null),
                anyBoolean(), anyBoolean());
@@ -7653,8 +7662,20 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
                .setContentTitle("foo")
                .setSmallIcon(android.R.drawable.sym_def_app_icon)
                .setStyle(new Notification.MessagingStyle("").addMessage(message2));
        NotificationRecord recordB = new NotificationRecord(mContext, new StatusBarNotification(mPkg,
                mPkg, 0, "tag", mUid, 0, nbB.build(), UserHandle.getUserHandleForUid(mUid), null, 0),
        NotificationRecord recordB =
                new NotificationRecord(
                        mContext,
                        new StatusBarNotification(
                                mPkg,
                                mPkg,
                                0,
                                "tag",
                                mUid,
                                0,
                                nbB.build(),
                                UserHandle.getUserHandleForUid(mUid),
                                null,
                                0),
                        c);
        // Update means we drop access to first
@@ -15356,8 +15377,13 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
        for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
            StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
                    i, null, false).getSbn();
            mBinderService.enqueueNotificationWithTag(mPkg, mPkg, "testCannotPostNonUijWhenOverLimit",
                    sbn.getId(), sbn.getNotification(), sbn.getUserId());
            mBinderService.enqueueNotificationWithTag(
                    mPkg,
                    mPkg,
                    "testCannotPostNonUijWhenOverLimit",
                    sbn.getId(),
                    sbn.getNotification(),
                    sbn.getUserId());
            waitForIdle();
        }
@@ -16087,6 +16113,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
        initNMS(SystemService.PHASE_SYSTEM_SERVICES_READY);
        mInternalService.setDeviceEffectsApplier(mock(DeviceEffectsApplier.class));
        mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START, mMainLooper);
        // No exception!
    }
+22 −5
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@ import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_CONTACTS;
import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_STARRED;
import static android.app.NotificationManager.Policy.STATE_PRIORITY_CHANNELS_BLOCKED;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_CONFIG;
import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_RULES;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Process.SYSTEM_UID;
import static android.provider.Settings.Global.ZEN_MODE_ALARMS;
@@ -84,8 +86,6 @@ import static com.android.os.dnd.DNDProtoEnums.PEOPLE_STARRED;
import static com.android.os.dnd.DNDProtoEnums.ROOT_CONFIG;
import static com.android.os.dnd.DNDProtoEnums.STATE_ALLOW;
import static com.android.os.dnd.DNDProtoEnums.STATE_DISALLOW;
import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_CONFIG;
import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_RULES;
import static com.android.server.notification.ZenModeEventLogger.ACTIVE_RULE_TYPE_MANUAL;
import static com.android.server.notification.ZenModeHelper.RULE_LIMIT_PER_PACKAGE;

@@ -102,6 +102,7 @@ import static junit.framework.TestCase.fail;

import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
@@ -200,6 +201,9 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.xmlpull.v1.XmlPullParserException;

import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
import platform.test.runner.parameterized.Parameters;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
@@ -219,9 +223,6 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
import platform.test.runner.parameterized.Parameters;

@SmallTest
@SuppressLint("GuardedBy") // It's ok for this test to access guarded methods from the service.
@RunWith(ParameterizedAndroidJunit4.class)
@@ -5332,6 +5333,22 @@ public class ZenModeHelperTest extends UiServiceTestCase {
        mTestableLooper.processAllMessages();

        verify(mDeviceEffectsApplier).apply(eq(effects), eq(ORIGIN_APP));
        assertTrue(mZenModeHelper.hasDeviceEffectsApplier());
    }

    @Test
    public void testHasDeviceEffectsApplier_returnsFalseIfNotSet() {
        assertFalse(mZenModeHelper.hasDeviceEffectsApplier());
    }

    @Test
    @EnableFlags(FLAG_MODES_API)
    public void testSettingDeviceEffects_throwsExceptionIfAlreadySet() {
        mZenModeHelper.setDeviceEffectsApplier(mDeviceEffectsApplier);

        assertThrows(
                IllegalStateException.class,
                () -> mZenModeHelper.setDeviceEffectsApplier(mDeviceEffectsApplier));
    }

    @Test