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

Commit acde600f authored by Fabián Kozynski's avatar Fabián Kozynski Committed by Fabian Kozynski
Browse files

Make ZenModeControllerImpl more robust

Also add some logs so we can track bad state.

Test: manual
Test: atest ZenModeControllerImplTest
Bug: 293807056
Change-Id: I6b9dda1c7904d980c92cc415513ba0f6cdb24017
parent 88c87429
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.provider.Settings.Global;
import android.service.notification.ZenModeConfig;
import android.service.quicksettings.Tile;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Switch;

@@ -315,6 +316,7 @@ public class DndTile extends QSTileImpl<BooleanState> {

    private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
        public void onZenChanged(int zen) {
            Log.d(TAG, "Zen changed to " + zen + ". Requesting refresh of tile.");
            refreshState(zen);
        }
    };
+18 −13
Original line number Diff line number Diff line
@@ -46,7 +46,6 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.qs.SettingObserver;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.Utils;
import com.android.systemui.util.settings.GlobalSettings;
@@ -68,17 +67,17 @@ public class ZenModeControllerImpl implements ZenModeController, Dumpable {
    private final Context mContext;
    private final UserTracker mUserTracker;
    private final BroadcastDispatcher mBroadcastDispatcher;
    private final SettingObserver mModeSetting;
    private final SettingObserver mConfigSetting;
    private final NotificationManager mNoMan;
    private final AlarmManager mAlarmManager;
    private final SetupObserver mSetupObserver;
    private final UserManager mUserManager;
    private final GlobalSettings mGlobalSettings;

    private int mUserId;
    private boolean mRegistered;
    private ZenModeConfig mConfig;
    private int mZenMode;
    // This value is changed in the main thread, but may be read in a background thread.
    private volatile int mZenMode;
    private long mZenUpdateTime;
    private NotificationManager.Policy mConsolidatedNotificationPolicy;

@@ -111,18 +110,20 @@ public class ZenModeControllerImpl implements ZenModeController, Dumpable {
        mContext = context;
        mBroadcastDispatcher = broadcastDispatcher;
        mUserTracker = userTracker;
        mModeSetting = new SettingObserver(globalSettings, handler, Global.ZEN_MODE,
                userTracker.getUserId()) {
        mGlobalSettings = globalSettings;

        ContentObserver modeContentObserver = new ContentObserver(handler) {
            @Override
            protected void handleValueChanged(int value, boolean observedChange) {
            public void onChange(boolean selfChange) {
                int value = getModeSettingValueFromProvider();
                Log.d(TAG, "Zen mode setting changed to " + value);
                updateZenMode(value);
                fireZenChanged(value);
            }
        };
        mConfigSetting = new SettingObserver(globalSettings, handler, Global.ZEN_MODE_CONFIG_ETAG,
                userTracker.getUserId()) {
        ContentObserver configContentObserver = new ContentObserver(handler) {
            @Override
            protected void handleValueChanged(int value, boolean observedChange) {
            public void onChange(boolean selfChange) {
                try {
                    Trace.beginSection("updateZenModeConfig");
                    updateZenModeConfig();
@@ -132,9 +133,9 @@ public class ZenModeControllerImpl implements ZenModeController, Dumpable {
            }
        };
        mNoMan = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        mModeSetting.setListening(true);
        updateZenMode(mModeSetting.getValue());
        mConfigSetting.setListening(true);
        globalSettings.registerContentObserver(Global.ZEN_MODE, modeContentObserver);
        updateZenMode(getModeSettingValueFromProvider());
        globalSettings.registerContentObserver(Global.ZEN_MODE_CONFIG_ETAG, configContentObserver);
        updateZenModeConfig();
        updateConsolidatedNotificationPolicy();
        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
@@ -146,6 +147,10 @@ public class ZenModeControllerImpl implements ZenModeController, Dumpable {
        dumpManager.registerDumpable(getClass().getSimpleName(), this);
    }

    private int getModeSettingValueFromProvider() {
        return mGlobalSettings.getInt(Global.ZEN_MODE, /* default */ Global.ZEN_MODE_OFF);
    }

    @Override
    public boolean isVolumeRestricted() {
        return mUserManager.hasUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME,
+53 −4
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@

package com.android.systemui.statusbar.policy;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;

@@ -24,10 +25,10 @@ import static org.mockito.Mockito.when;

import android.app.NotificationManager;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;

import androidx.test.filters.SmallTest;
@@ -45,6 +46,9 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@@ -61,9 +65,10 @@ public class ZenModeControllerImplTest extends SysuiTestCase {
    DumpManager mDumpManager;
    @Mock
    UserTracker mUserTracker;

    private ZenModeControllerImpl mController;

    private final FakeSettings mGlobalSettings = new FakeSettings();

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
@@ -72,10 +77,10 @@ public class ZenModeControllerImplTest extends SysuiTestCase {

        mController = new ZenModeControllerImpl(
                mContext,
                Handler.createAsync(Looper.myLooper()),
                Handler.createAsync(TestableLooper.get(this).getLooper()),
                mBroadcastDispatcher,
                mDumpManager,
                new FakeSettings(),
                mGlobalSettings,
                mUserTracker);
    }

@@ -131,4 +136,48 @@ public class ZenModeControllerImplTest extends SysuiTestCase {
        mController.addCallback(null);
        mController.fireConfigChanged(null);
    }

    @Test
    public void testModeChange() {
        List<Integer> states = List.of(
                Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
                Settings.Global.ZEN_MODE_NO_INTERRUPTIONS,
                Settings.Global.ZEN_MODE_ALARMS,
                Settings.Global.ZEN_MODE_ALARMS
        );

        for (Integer state : states) {
            mGlobalSettings.putInt(Settings.Global.ZEN_MODE, state);
            TestableLooper.get(this).processAllMessages();
            assertEquals(state.intValue(), mController.getZen());
        }
    }

    @Test
    public void testModeChange_callbackNotified() {
        final AtomicInteger currentState = new AtomicInteger(-1);

        ZenModeController.Callback callback = new Callback() {
            @Override
            public void onZenChanged(int zen) {
                currentState.set(zen);
            }
        };

        mController.addCallback(callback);

        List<Integer> states = List.of(
                Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
                Settings.Global.ZEN_MODE_NO_INTERRUPTIONS,
                Settings.Global.ZEN_MODE_ALARMS,
                Settings.Global.ZEN_MODE_ALARMS
        );

        for (Integer state : states) {
            mGlobalSettings.putInt(Settings.Global.ZEN_MODE, state);
            TestableLooper.get(this).processAllMessages();
            assertEquals(state.intValue(), currentState.get());
        }

    }
}