From 29d65f5e3d5f170d350f7c59c821994b96b0e6d6 Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Wed, 22 Apr 2020 09:27:25 -0400 Subject: Add multi-user support for AutoTileManager Before this CL, AutoTileManager (and AutoAddTracker) would only work "corectly" for user 0, as all the settings (read and write) were done in user 0. This meant that tiles that got auto added as user 0 would not be auto-added for other users. Similarly, tiles that got auto added as a secondary user would not be auto added as user 0. This CL makes sure that everything is done with respect to the current user (as reported by QSTileHost). Test: manual Test: atest AutoTileManagerTest AutoAddTrackerTest Fixes: 154607890 Change-Id: I90717dedc8935dd2597e504acd57f5b44236ef3e Merged-In: I518334cca0a0960e0b3b74b43ac9fce4610c7bd0 --- .../systemui/controls/UserAwareController.kt | 28 ---- .../controller/ControlsBindingController.kt | 2 +- .../controls/controller/ControlsController.kt | 2 +- .../management/ControlsListingController.kt | 4 +- .../com/android/systemui/qs/AutoAddTracker.java | 64 +++++++-- .../src/com/android/systemui/qs/QSTileHost.java | 3 + .../systemui/statusbar/phone/AutoTileManager.java | 78 +++++++--- .../android/systemui/util/UserAwareController.kt | 30 ++++ .../android/systemui/qs/AutoAddTrackerTest.java | 32 ++++- .../statusbar/phone/AutoTileManagerTest.java | 157 +++++++++++++++++++-- 10 files changed, 325 insertions(+), 75 deletions(-) delete mode 100644 packages/SystemUI/src/com/android/systemui/controls/UserAwareController.kt create mode 100644 packages/SystemUI/src/com/android/systemui/util/UserAwareController.kt diff --git a/packages/SystemUI/src/com/android/systemui/controls/UserAwareController.kt b/packages/SystemUI/src/com/android/systemui/controls/UserAwareController.kt deleted file mode 100644 index d2776d27ae62..000000000000 --- a/packages/SystemUI/src/com/android/systemui/controls/UserAwareController.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2020 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.systemui.controls - -import android.os.UserHandle - -/** - * An interface for controllers that keep track of the current user and can be notified of user - * changes. - */ -interface UserAwareController { - fun changeUser(newUser: UserHandle) {} - val currentUserId: Int -} \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt index d4d4d2a7d8fe..eed55315e836 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt @@ -20,7 +20,7 @@ import android.content.ComponentName import android.service.controls.Control import android.service.controls.ControlsProviderService import android.service.controls.actions.ControlAction -import com.android.systemui.controls.UserAwareController +import com.android.systemui.util.UserAwareController import java.util.function.Consumer /** diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt index 07319207d9ab..b83684df5c29 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt @@ -21,7 +21,7 @@ import android.service.controls.Control import android.service.controls.ControlsProviderService import android.service.controls.actions.ControlAction import com.android.systemui.controls.ControlStatus -import com.android.systemui.controls.UserAwareController +import com.android.systemui.util.UserAwareController import com.android.systemui.controls.management.ControlsFavoritingActivity import com.android.systemui.controls.ui.ControlsUiController import java.util.function.Consumer diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt index 647daccca8bd..b9f16665944f 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt @@ -18,7 +18,7 @@ package com.android.systemui.controls.management import android.content.ComponentName import com.android.systemui.controls.ControlsServiceInfo -import com.android.systemui.controls.UserAwareController +import com.android.systemui.util.UserAwareController import com.android.systemui.statusbar.policy.CallbackController /** @@ -26,7 +26,7 @@ import com.android.systemui.statusbar.policy.CallbackController */ interface ControlsListingController : CallbackController, - UserAwareController { + UserAwareController { /** * @return the current list of services that satisfies the [ServiceListing]. diff --git a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java index 2365e67fec2f..0a84f5ee1bb9 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java +++ b/packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.java @@ -23,6 +23,7 @@ import static com.android.systemui.statusbar.phone.AutoTileManager.WORK; import android.content.Context; import android.database.ContentObserver; import android.os.Handler; +import android.os.UserHandle; import android.provider.Settings.Secure; import android.text.TextUtils; import android.util.ArraySet; @@ -30,6 +31,7 @@ import android.util.ArraySet; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Prefs; import com.android.systemui.Prefs.Key; +import com.android.systemui.util.UserAwareController; import java.util.Arrays; import java.util.Collection; @@ -37,7 +39,7 @@ import java.util.Collections; import javax.inject.Inject; -public class AutoAddTracker { +public class AutoAddTracker implements UserAwareController { private static final String[][] CONVERT_PREFS = { {Key.QS_HOTSPOT_ADDED, HOTSPOT}, @@ -49,20 +51,39 @@ public class AutoAddTracker { private final ArraySet mAutoAdded; private final Context mContext; + private int mUserId; - @Inject - public AutoAddTracker(Context context) { + public AutoAddTracker(Context context, int userId) { mContext = context; + mUserId = userId; mAutoAdded = new ArraySet<>(getAdded()); // TODO: remove migration code and shared preferences keys after P release - for (String[] convertPref : CONVERT_PREFS) { - if (Prefs.getBoolean(context, convertPref[0], false)) { - setTileAdded(convertPref[1]); - Prefs.remove(context, convertPref[0]); + if (mUserId == UserHandle.USER_SYSTEM) { + for (String[] convertPref : CONVERT_PREFS) { + if (Prefs.getBoolean(context, convertPref[0], false)) { + setTileAdded(convertPref[1]); + Prefs.remove(context, convertPref[0]); + } } } mContext.getContentResolver().registerContentObserver( - Secure.getUriFor(Secure.QS_AUTO_ADDED_TILES), false, mObserver); + Secure.getUriFor(Secure.QS_AUTO_ADDED_TILES), false, mObserver, + UserHandle.USER_ALL); + } + + @Override + public void changeUser(UserHandle newUser) { + if (newUser.getIdentifier() == mUserId) { + return; + } + mUserId = newUser.getIdentifier(); + mAutoAdded.clear(); + mAutoAdded.addAll(getAdded()); + } + + @Override + public int getCurrentUserId() { + return mUserId; } public boolean isAdded(String tile) { @@ -86,12 +107,13 @@ public class AutoAddTracker { } private void saveTiles() { - Secure.putString(mContext.getContentResolver(), Secure.QS_AUTO_ADDED_TILES, - TextUtils.join(",", mAutoAdded)); + Secure.putStringForUser(mContext.getContentResolver(), Secure.QS_AUTO_ADDED_TILES, + TextUtils.join(",", mAutoAdded), mUserId); } private Collection getAdded() { - String current = Secure.getString(mContext.getContentResolver(), Secure.QS_AUTO_ADDED_TILES); + String current = Secure.getStringForUser(mContext.getContentResolver(), + Secure.QS_AUTO_ADDED_TILES, mUserId); if (current == null) { return Collections.emptyList(); } @@ -102,7 +124,27 @@ public class AutoAddTracker { protected final ContentObserver mObserver = new ContentObserver(new Handler()) { @Override public void onChange(boolean selfChange) { + mAutoAdded.clear(); mAutoAdded.addAll(getAdded()); } }; + + public static class Builder { + private final Context mContext; + private int mUserId; + + @Inject + public Builder(Context context) { + mContext = context; + } + + public Builder setUserId(int userId) { + mUserId = userId; + return this; + } + + public AutoAddTracker build() { + return new AutoAddTracker(mContext, mUserId); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java index 4008918e267c..d3a341b9c06a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java @@ -255,6 +255,9 @@ public class QSTileHost implements QSHost, Tunable, PluginListener, D int currentUser = ActivityManager.getCurrentUser(); if (currentUser != mCurrentUser) { mUserContext = mContext.createContextAsUser(UserHandle.of(currentUser), 0); + if (mAutoTiles != null) { + mAutoTiles.changeUser(UserHandle.of(currentUser)); + } } if (tileSpecs.equals(mTileSpecs) && currentUser == mCurrentUser) return; mTiles.entrySet().stream().filter(tile -> !tileSpecs.contains(tile.getKey())).forEach( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java index 79515415f1c3..0d75da2b4817 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java @@ -19,6 +19,7 @@ import android.content.res.Resources; import android.hardware.display.ColorDisplayManager; import android.hardware.display.NightDisplayListener; import android.os.Handler; +import android.os.UserHandle; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; @@ -34,6 +35,7 @@ import com.android.systemui.statusbar.policy.DataSaverController; import com.android.systemui.statusbar.policy.DataSaverController.Listener; import com.android.systemui.statusbar.policy.HotspotController; import com.android.systemui.statusbar.policy.HotspotController.Callback; +import com.android.systemui.util.UserAwareController; import java.util.ArrayList; import java.util.Objects; @@ -43,7 +45,7 @@ import javax.inject.Inject; /** * Manages which tiles should be automatically added to QS. */ -public class AutoTileManager { +public class AutoTileManager implements UserAwareController { private static final String TAG = "AutoTileManager"; public static final String HOTSPOT = "hotspot"; @@ -52,7 +54,9 @@ public class AutoTileManager { public static final String WORK = "work"; public static final String NIGHT = "night"; public static final String CAST = "cast"; - public static final String SETTING_SEPARATOR = ":"; + static final String SETTING_SEPARATOR = ":"; + + private UserHandle mCurrentUser; private final Context mContext; private final QSTileHost mHost; @@ -66,43 +70,56 @@ public class AutoTileManager { private final ArrayList mAutoAddSettingList = new ArrayList<>(); @Inject - public AutoTileManager(Context context, AutoAddTracker autoAddTracker, QSTileHost host, + public AutoTileManager(Context context, AutoAddTracker.Builder autoAddTrackerBuilder, + QSTileHost host, @Background Handler handler, HotspotController hotspotController, DataSaverController dataSaverController, ManagedProfileController managedProfileController, NightDisplayListener nightDisplayListener, CastController castController) { - mAutoTracker = autoAddTracker; mContext = context; mHost = host; + mCurrentUser = mHost.getUserContext().getUser(); + mAutoTracker = autoAddTrackerBuilder.setUserId(mCurrentUser.getIdentifier()).build(); mHandler = handler; mHotspotController = hotspotController; mDataSaverController = dataSaverController; mManagedProfileController = managedProfileController; mNightDisplayListener = nightDisplayListener; mCastController = castController; + + populateSettingsList(); + startControllersAndSettingsListeners(); + } + + protected void startControllersAndSettingsListeners() { if (!mAutoTracker.isAdded(HOTSPOT)) { - hotspotController.addCallback(mHotspotCallback); + mHotspotController.addCallback(mHotspotCallback); } if (!mAutoTracker.isAdded(SAVER)) { - dataSaverController.addCallback(mDataSaverListener); + mDataSaverController.addCallback(mDataSaverListener); } if (!mAutoTracker.isAdded(WORK)) { - managedProfileController.addCallback(mProfileCallback); + mManagedProfileController.addCallback(mProfileCallback); } if (!mAutoTracker.isAdded(NIGHT) && ColorDisplayManager.isNightDisplayAvailable(mContext)) { - nightDisplayListener.setCallback(mNightDisplayCallback); + mNightDisplayListener.setCallback(mNightDisplayCallback); } if (!mAutoTracker.isAdded(CAST)) { - castController.addCallback(mCastCallback); + mCastController.addCallback(mCastCallback); + } + + int settingsN = mAutoAddSettingList.size(); + for (int i = 0; i < settingsN; i++) { + if (!mAutoTracker.isAdded(mAutoAddSettingList.get(i).mSpec)) { + mAutoAddSettingList.get(i).setListening(true); + } } - populateSettingsList(); } - public void destroy() { - mAutoTracker.destroy(); + protected void stopListening() { mHotspotController.removeCallback(mHotspotCallback); mDataSaverController.removeCallback(mDataSaverListener); mManagedProfileController.removeCallback(mProfileCallback); @@ -116,6 +133,11 @@ public class AutoTileManager { } } + public void destroy() { + stopListening(); + mAutoTracker.destroy(); + } + /** * Populates a list with the pairs setting:spec in the config resource. *

@@ -137,17 +159,39 @@ public class AutoTileManager { if (split.length == 2) { String setting = split[0]; String spec = split[1]; - if (!mAutoTracker.isAdded(spec)) { - AutoAddSetting s = new AutoAddSetting(mContext, mHandler, setting, spec); - mAutoAddSettingList.add(s); - s.setListening(true); - } + // Populate all the settings. As they may not have been added in other users + AutoAddSetting s = new AutoAddSetting(mContext, mHandler, setting, spec); + mAutoAddSettingList.add(s); } else { Log.w(TAG, "Malformed item in array: " + tile); } } } + @Override + public void changeUser(UserHandle newUser) { + if (!Thread.currentThread().equals(mHandler.getLooper().getThread())) { + mHandler.post(() -> changeUser(newUser)); + return; + } + if (newUser.getIdentifier() == mCurrentUser.getIdentifier()) { + return; + } + stopListening(); + mCurrentUser = newUser; + int settingsN = mAutoAddSettingList.size(); + for (int i = 0; i < settingsN; i++) { + mAutoAddSettingList.get(i).setUserId(newUser.getIdentifier()); + } + mAutoTracker.changeUser(newUser); + startControllersAndSettingsListeners(); + } + + @Override + public int getCurrentUserId() { + return mCurrentUser.getIdentifier(); + } + public void unmarkTileAsAutoAdded(String tabSpec) { mAutoTracker.setTileRemoved(tabSpec); } diff --git a/packages/SystemUI/src/com/android/systemui/util/UserAwareController.kt b/packages/SystemUI/src/com/android/systemui/util/UserAwareController.kt new file mode 100644 index 000000000000..693c2708b0f7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/UserAwareController.kt @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2020 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.systemui.util + +import android.os.UserHandle + +/** + * An interface for controllers that keep track of the current user and can be notified of user + * changes. + */ +interface UserAwareController { + @JvmDefault + fun changeUser(newUser: UserHandle) {} + + val currentUserId: Int +} \ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java index 0ae9461d38b1..61f5a7bdd3b7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/AutoAddTrackerTest.java @@ -21,6 +21,7 @@ import static com.android.systemui.statusbar.phone.AutoTileManager.WORK; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import android.os.UserHandle; import android.provider.Settings.Secure; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; @@ -40,6 +41,8 @@ import org.junit.runner.RunWith; @SmallTest public class AutoAddTrackerTest extends SysuiTestCase { + private static final int USER = 0; + private AutoAddTracker mAutoTracker; @Before @@ -51,7 +54,7 @@ public class AutoAddTrackerTest extends SysuiTestCase { public void testMigration() { Prefs.putBoolean(mContext, Key.QS_DATA_SAVER_ADDED, true); Prefs.putBoolean(mContext, Key.QS_WORK_ADDED, true); - mAutoTracker = new AutoAddTracker(mContext); + mAutoTracker = new AutoAddTracker(mContext, USER); assertTrue(mAutoTracker.isAdded(SAVER)); assertTrue(mAutoTracker.isAdded(WORK)); @@ -68,7 +71,7 @@ public class AutoAddTrackerTest extends SysuiTestCase { @Test public void testChangeFromBackup() { - mAutoTracker = new AutoAddTracker(mContext); + mAutoTracker = new AutoAddTracker(mContext, USER); assertFalse(mAutoTracker.isAdded(SAVER)); @@ -82,7 +85,7 @@ public class AutoAddTrackerTest extends SysuiTestCase { @Test public void testSetAdded() { - mAutoTracker = new AutoAddTracker(mContext); + mAutoTracker = new AutoAddTracker(mContext, USER); assertFalse(mAutoTracker.isAdded(SAVER)); mAutoTracker.setTileAdded(SAVER); @@ -94,16 +97,35 @@ public class AutoAddTrackerTest extends SysuiTestCase { @Test public void testPersist() { - mAutoTracker = new AutoAddTracker(mContext); + mAutoTracker = new AutoAddTracker(mContext, USER); assertFalse(mAutoTracker.isAdded(SAVER)); mAutoTracker.setTileAdded(SAVER); mAutoTracker.destroy(); - mAutoTracker = new AutoAddTracker(mContext); + mAutoTracker = new AutoAddTracker(mContext, USER); assertTrue(mAutoTracker.isAdded(SAVER)); mAutoTracker.destroy(); } + + @Test + public void testIndependentUsers() { + mAutoTracker = new AutoAddTracker(mContext, USER); + mAutoTracker.setTileAdded(SAVER); + + mAutoTracker = new AutoAddTracker(mContext, USER + 1); + assertFalse(mAutoTracker.isAdded(SAVER)); + } + + @Test + public void testChangeUser() { + mAutoTracker = new AutoAddTracker(mContext, USER); + mAutoTracker.setTileAdded(SAVER); + + mAutoTracker = new AutoAddTracker(mContext, USER + 1); + mAutoTracker.changeUser(UserHandle.of(USER)); + assertTrue(mAutoTracker.isAdded(SAVER)); + } } \ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java index 1a6921a1d136..10d000c7b227 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java @@ -16,18 +16,34 @@ package com.android.systemui.statusbar.phone; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.isNotNull; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ComponentName; +import android.content.ContentResolver; +import android.content.Context; +import android.content.ContextWrapper; import android.hardware.display.ColorDisplayManager; import android.hardware.display.NightDisplayListener; import android.os.Handler; +import android.os.UserHandle; import android.provider.Settings; import android.testing.AndroidTestingRunner; +import android.testing.TestableContentResolver; +import android.testing.TestableContext; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; @@ -38,14 +54,18 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.qs.AutoAddTracker; import com.android.systemui.qs.QSTileHost; import com.android.systemui.qs.SecureSetting; +import com.android.systemui.statusbar.phone.AutoTileManagerTest.MyContextWrapper; import com.android.systemui.statusbar.policy.CastController; import com.android.systemui.statusbar.policy.CastController.CastDevice; import com.android.systemui.statusbar.policy.DataSaverController; import com.android.systemui.statusbar.policy.HotspotController; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -64,9 +84,18 @@ public class AutoTileManagerTest extends SysuiTestCase { private static final String TEST_CUSTOM_SPEC = "custom(" + TEST_COMPONENT + ")"; private static final String SEPARATOR = AutoTileManager.SETTING_SEPARATOR; + private static final int USER = 0; + @Mock private QSTileHost mQsTileHost; @Mock private AutoAddTracker mAutoAddTracker; @Mock private CastController mCastController; + @Mock private HotspotController mHotspotController; + @Mock private DataSaverController mDataSaverController; + @Mock private ManagedProfileController mManagedProfileController; + @Mock private NightDisplayListener mNightDisplayListener; + @Mock(answer = Answers.RETURNS_SELF) + private AutoAddTracker.Builder mAutoAddTrackerBuilder; + @Mock private Context mUserContext; private AutoTileManager mAutoTileManager; @@ -82,19 +111,109 @@ public class AutoTileManagerTest extends SysuiTestCase { } ); - mAutoTileManager = createAutoTileManager(); + when(mAutoAddTrackerBuilder.build()).thenReturn(mAutoAddTracker); + when(mQsTileHost.getUserContext()).thenReturn(mUserContext); + when(mUserContext.getUser()).thenReturn(UserHandle.of(USER)); + + mAutoTileManager = createAutoTileManager(new + MyContextWrapper(mContext)); } - private AutoTileManager createAutoTileManager() { - return new AutoTileManager(mContext, mAutoAddTracker, mQsTileHost, + @After + public void tearDown() { + mAutoTileManager.destroy(); + } + + private AutoTileManager createAutoTileManager(Context context) { + return new AutoTileManager(context, mAutoAddTrackerBuilder, mQsTileHost, Handler.createAsync(TestableLooper.get(this).getLooper()), - mock(HotspotController.class), - mock(DataSaverController.class), - mock(ManagedProfileController.class), - mock(NightDisplayListener.class), + mHotspotController, + mDataSaverController, + mManagedProfileController, + mNightDisplayListener, mCastController); } + @Test + public void testChangeUserCallbacksStoppedAndStarted() throws Exception { + TestableLooper.get(this).runWithLooper(() -> + mAutoTileManager.changeUser(UserHandle.of(USER + 1)) + ); + + InOrder inOrderHotspot = inOrder(mHotspotController); + inOrderHotspot.verify(mHotspotController).removeCallback(any()); + inOrderHotspot.verify(mHotspotController).addCallback(any()); + + InOrder inOrderDataSaver = inOrder(mDataSaverController); + inOrderDataSaver.verify(mDataSaverController).removeCallback(any()); + inOrderDataSaver.verify(mDataSaverController).addCallback(any()); + + InOrder inOrderManagedProfile = inOrder(mManagedProfileController); + inOrderManagedProfile.verify(mManagedProfileController).removeCallback(any()); + inOrderManagedProfile.verify(mManagedProfileController).addCallback(any()); + + InOrder inOrderNightDisplay = inOrder(mNightDisplayListener); + inOrderNightDisplay.verify(mNightDisplayListener).setCallback(isNull()); + inOrderNightDisplay.verify(mNightDisplayListener).setCallback(isNotNull()); + + InOrder inOrderCast = inOrder(mCastController); + inOrderCast.verify(mCastController).removeCallback(any()); + inOrderCast.verify(mCastController).addCallback(any()); + + SecureSetting setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING); + assertEquals(USER + 1, setting.getCurrentUser()); + assertTrue(setting.isListening()); + } + + @Test + public void testChangeUserSomeCallbacksNotAdded() throws Exception { + when(mAutoAddTracker.isAdded("hotspot")).thenReturn(true); + when(mAutoAddTracker.isAdded("work")).thenReturn(true); + when(mAutoAddTracker.isAdded("cast")).thenReturn(true); + when(mAutoAddTracker.isAdded(TEST_SPEC)).thenReturn(true); + + TestableLooper.get(this).runWithLooper(() -> + mAutoTileManager.changeUser(UserHandle.of(USER + 1)) + ); + + verify(mAutoAddTracker).changeUser(UserHandle.of(USER + 1)); + + InOrder inOrderHotspot = inOrder(mHotspotController); + inOrderHotspot.verify(mHotspotController).removeCallback(any()); + inOrderHotspot.verify(mHotspotController, never()).addCallback(any()); + + InOrder inOrderDataSaver = inOrder(mDataSaverController); + inOrderDataSaver.verify(mDataSaverController).removeCallback(any()); + inOrderDataSaver.verify(mDataSaverController).addCallback(any()); + + InOrder inOrderManagedProfile = inOrder(mManagedProfileController); + inOrderManagedProfile.verify(mManagedProfileController).removeCallback(any()); + inOrderManagedProfile.verify(mManagedProfileController, never()).addCallback(any()); + + InOrder inOrderNightDisplay = inOrder(mNightDisplayListener); + inOrderNightDisplay.verify(mNightDisplayListener).setCallback(isNull()); + inOrderNightDisplay.verify(mNightDisplayListener).setCallback(isNotNull()); + + InOrder inOrderCast = inOrder(mCastController); + inOrderCast.verify(mCastController).removeCallback(any()); + inOrderCast.verify(mCastController, never()).addCallback(any()); + + SecureSetting setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING); + assertEquals(USER + 1, setting.getCurrentUser()); + assertFalse(setting.isListening()); + } + + @Test + public void testGetCurrentUserId() throws Exception { + assertEquals(USER, mAutoTileManager.getCurrentUserId()); + + TestableLooper.get(this).runWithLooper(() -> + mAutoTileManager.changeUser(UserHandle.of(USER + 100)) + ); + + assertEquals(USER + 100, mAutoTileManager.getCurrentUserId()); + } + @Test public void nightTileAdded_whenActivated() { if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) { @@ -212,14 +331,14 @@ public class AutoTileManagerTest extends SysuiTestCase { public void testEmptyArray_doesNotCrash() { mContext.getOrCreateTestableResources().addOverride( R.array.config_quickSettingsAutoAdd, new String[0]); - createAutoTileManager(); + createAutoTileManager(mContext).destroy(); } @Test public void testMissingConfig_doesNotCrash() { mContext.getOrCreateTestableResources().addOverride( R.array.config_quickSettingsAutoAdd, null); - createAutoTileManager(); + createAutoTileManager(mContext).destroy(); } // Will only notify if it's listening @@ -230,4 +349,22 @@ public class AutoTileManagerTest extends SysuiTestCase { s.onChange(false); } } + + class MyContextWrapper extends ContextWrapper { + + private TestableContentResolver mSpiedTCR; + + MyContextWrapper(TestableContext context) { + super(context); + mSpiedTCR = spy(context.getContentResolver()); + doNothing().when(mSpiedTCR).registerContentObserver(any(), anyBoolean(), any(), + anyInt()); + doNothing().when(mSpiedTCR).unregisterContentObserver(any()); + } + + @Override + public ContentResolver getContentResolver() { + return mSpiedTCR; + } + } } -- cgit v1.2.3-59-g8ed1b