Make ZenModeControllerImpl more robust Also add some logs so we can track bad state. Test: manual Test: atest ZenModeControllerImplTest Bug: 293807056 Change-Id: I6b9dda1c7904d980c92cc415513ba0f6cdb24017
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index 3e7bdd1..9bb192b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -34,6 +34,7 @@ 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 @@ 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); } };
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java index 1c3a8850..dabdcc5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -46,7 +46,6 @@ 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 @@ 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 @@ 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 @@ } }; 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 @@ 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,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java index c06dbdc..7f3d4b7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java
@@ -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 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.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 @@ 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 @@ mController = new ZenModeControllerImpl( mContext, - Handler.createAsync(Looper.myLooper()), + Handler.createAsync(TestableLooper.get(this).getLooper()), mBroadcastDispatcher, mDumpManager, - new FakeSettings(), + mGlobalSettings, mUserTracker); } @@ -131,4 +136,48 @@ 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()); + } + + } }