diff options
| author | 2019-04-10 13:48:02 -0400 | |
|---|---|---|
| committer | 2019-04-10 13:53:16 -0400 | |
| commit | be2a1885d33d11c4cc74b263f2bb2ea11341dc5c (patch) | |
| tree | 53fac77826e47a140d300372a61b43243d69b762 | |
| parent | 372e13ff25c640fc31db3270f047eb0f43fc191c (diff) | |
Add tests for user changes.
These are regression tests for b/128607948.
Bug: 130236375
Test: New test points added to ClockManagerTest
Change-Id: Ic9b7d73174b99beb43b518235e89d29c54a7375b
3 files changed, 134 insertions, 23 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java index bc00b5cf9a45..677a3b286d73 100644 --- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java +++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java @@ -30,6 +30,7 @@ import android.util.DisplayMetrics; import android.view.LayoutInflater; import androidx.annotation.VisibleForTesting; +import androidx.lifecycle.Observer; import com.android.systemui.SysUiServiceProvider; import com.android.systemui.colorextraction.SysuiColorExtractor; @@ -37,13 +38,14 @@ import com.android.systemui.dock.DockManager; import com.android.systemui.dock.DockManager.DockEventListener; import com.android.systemui.plugins.ClockPlugin; import com.android.systemui.plugins.PluginListener; -import com.android.systemui.settings.CurrentUserTracker; +import com.android.systemui.settings.CurrentUserObservable; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.util.InjectionInflationController; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.function.Supplier; import javax.inject.Inject; @@ -64,7 +66,7 @@ public final class ClockManager { private final ContentResolver mContentResolver; private final SettingsWrapper mSettingsWrapper; private final Handler mMainHandler = new Handler(Looper.getMainLooper()); - private final CurrentUserTracker mCurrentUserTracker; + private final CurrentUserObservable mCurrentUserObservable; /** * Observe settings changes to know when to switch the clock face. @@ -74,12 +76,18 @@ public final class ClockManager { @Override public void onChange(boolean selfChange, Uri uri, int userId) { super.onChange(selfChange, uri, userId); - if (userId == mCurrentUserTracker.getCurrentUserId()) { + if (Objects.equals(userId, + mCurrentUserObservable.getCurrentUser().getValue())) { reload(); } } }; + /** + * Observe user changes and react by potentially loading the custom clock for the new user. + */ + private final Observer<Integer> mCurrentUserObserver = (newUserId) -> reload(); + private final PluginManager mPluginManager; /** @@ -119,22 +127,19 @@ public final class ClockManager { public ClockManager(Context context, InjectionInflationController injectionInflater, PluginManager pluginManager, SysuiColorExtractor colorExtractor) { this(context, injectionInflater, pluginManager, colorExtractor, - context.getContentResolver(), new SettingsWrapper(context.getContentResolver())); + context.getContentResolver(), new CurrentUserObservable(context), + new SettingsWrapper(context.getContentResolver())); } ClockManager(Context context, InjectionInflationController injectionInflater, PluginManager pluginManager, SysuiColorExtractor colorExtractor, - ContentResolver contentResolver, SettingsWrapper settingsWrapper) { + ContentResolver contentResolver, CurrentUserObservable currentUserObservable, + SettingsWrapper settingsWrapper) { mContext = context; mPluginManager = pluginManager; mContentResolver = contentResolver; mSettingsWrapper = settingsWrapper; - mCurrentUserTracker = new CurrentUserTracker(context) { - @Override - public void onUserSwitched(int newUserId) { - reload(); - } - }; + mCurrentUserObservable = currentUserObservable; mPreviewClocks = new AvailableClocks(); Resources res = context.getResources(); @@ -219,7 +224,7 @@ public final class ClockManager { mContentResolver.registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.DOCKED_CLOCK_FACE), false, mContentObserver, UserHandle.USER_ALL); - mCurrentUserTracker.startTracking(); + mCurrentUserObservable.getCurrentUser().observeForever(mCurrentUserObserver); if (mDockManager == null) { mDockManager = SysUiServiceProvider.getComponent(mContext, DockManager.class); } @@ -231,7 +236,7 @@ public final class ClockManager { private void unregister() { mPluginManager.removePluginListener(mPreviewClocks); mContentResolver.unregisterContentObserver(mContentObserver); - mCurrentUserTracker.stopTracking(); + mCurrentUserObservable.getCurrentUser().removeObserver(mCurrentUserObserver); if (mDockManager != null) { mDockManager.removeListener(mDockEventListener); } @@ -349,7 +354,7 @@ public final class ClockManager { ClockPlugin plugin = null; if (ClockManager.this.isDocked()) { final String name = mSettingsWrapper.getDockedClockFace( - mCurrentUserTracker.getCurrentUserId()); + mCurrentUserObservable.getCurrentUser().getValue()); if (name != null) { plugin = mClocks.get(name); if (plugin != null) { @@ -358,7 +363,7 @@ public final class ClockManager { } } final String name = mSettingsWrapper.getLockScreenCustomClockFace( - mCurrentUserTracker.getCurrentUserId()); + mCurrentUserObservable.getCurrentUser().getValue()); if (name != null) { plugin = mClocks.get(name); } diff --git a/packages/SystemUI/src/com/android/systemui/settings/CurrentUserObservable.java b/packages/SystemUI/src/com/android/systemui/settings/CurrentUserObservable.java new file mode 100644 index 000000000000..3cf08b4b866e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/settings/CurrentUserObservable.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2019 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.settings; + +import android.content.Context; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; + +/** + * A class that has an observable for the current user. + */ +public class CurrentUserObservable { + + private final CurrentUserTracker mTracker; + + private final MutableLiveData<Integer> mCurrentUser = new MutableLiveData<Integer>() { + @Override + protected void onActive() { + super.onActive(); + mTracker.startTracking(); + } + + @Override + protected void onInactive() { + super.onInactive(); + mTracker.startTracking(); + } + }; + + public CurrentUserObservable(Context context) { + mTracker = new CurrentUserTracker(context) { + @Override + public void onUserSwitched(int newUserId) { + mCurrentUser.setValue(newUserId); + } + }; + } + + /** + * Returns the current user that can be observed. + */ + public LiveData<Integer> getCurrentUser() { + if (mCurrentUser.getValue() == null) { + mCurrentUser.setValue(mTracker.getCurrentUserId()); + } + return mCurrentUser; + } +} diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java index 17fbe09e07b3..76f1684aae7a 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java @@ -31,11 +31,14 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import android.view.LayoutInflater; +import androidx.lifecycle.MutableLiveData; + import com.android.systemui.SysuiTestCase; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dock.DockManager; import com.android.systemui.dock.DockManagerFake; import com.android.systemui.plugins.ClockPlugin; +import com.android.systemui.settings.CurrentUserObservable; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.util.InjectionInflationController; @@ -49,21 +52,26 @@ import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidTestingRunner.class) -@RunWithLooper +// Need to run tests on main looper because LiveData operations such as setData, observe, +// removeObserver cannot be invoked on a background thread. +@RunWithLooper(setAsMainLooper = true) public final class ClockManagerTest extends SysuiTestCase { private static final String BUBBLE_CLOCK = BubbleClockController.class.getName(); private static final Class<?> BUBBLE_CLOCK_CLASS = BubbleClockController.class; - private static final int USER_ID = 0; + private static final int MAIN_USER_ID = 0; + private static final int SECONDARY_USER_ID = 11; private static final Uri SETTINGS_URI = null; private ClockManager mClockManager; private ContentObserver mContentObserver; private DockManagerFake mFakeDockManager; + private MutableLiveData<Integer> mCurrentUser; @Mock InjectionInflationController mMockInjectionInflationController; @Mock PluginManager mMockPluginManager; @Mock SysuiColorExtractor mMockColorExtractor; @Mock ContentResolver mMockContentResolver; + @Mock CurrentUserObservable mMockCurrentUserObserable; @Mock SettingsWrapper mMockSettingsWrapper; @Mock ClockManager.ClockChangedListener mMockListener1; @Mock ClockManager.ClockChangedListener mMockListener2; @@ -78,9 +86,13 @@ public final class ClockManagerTest extends SysuiTestCase { mFakeDockManager = new DockManagerFake(); getContext().putComponent(DockManager.class, mFakeDockManager); + mCurrentUser = new MutableLiveData<>(); + mCurrentUser.setValue(MAIN_USER_ID); + when(mMockCurrentUserObserable.getCurrentUser()).thenReturn(mCurrentUser); + mClockManager = new ClockManager(getContext(), mMockInjectionInflationController, mMockPluginManager, mMockColorExtractor, mMockContentResolver, - mMockSettingsWrapper); + mMockCurrentUserObserable, mMockSettingsWrapper); mClockManager.addOnClockChangedListener(mMockListener1); mClockManager.addOnClockChangedListener(mMockListener2); @@ -113,7 +125,7 @@ public final class ClockManagerTest extends SysuiTestCase { when(mMockSettingsWrapper.getLockScreenCustomClockFace(anyInt())).thenReturn(null); when(mMockSettingsWrapper.getDockedClockFace(anyInt())).thenReturn(null); // WHEN settings change event is fired - mContentObserver.onChange(false, SETTINGS_URI, USER_ID); + mContentObserver.onChange(false, SETTINGS_URI, MAIN_USER_ID); // THEN the result is null, indicated the default clock face should be used. assertThat(mClockManager.getCurrentClock()).isNull(); } @@ -123,7 +135,7 @@ public final class ClockManagerTest extends SysuiTestCase { // GIVEN that settings is set to the bubble clock face when(mMockSettingsWrapper.getLockScreenCustomClockFace(anyInt())).thenReturn(BUBBLE_CLOCK); // WHEN settings change event is fired - mContentObserver.onChange(false, SETTINGS_URI, USER_ID); + mContentObserver.onChange(false, SETTINGS_URI, MAIN_USER_ID); // THEN the plugin is the bubble clock face. assertThat(mClockManager.getCurrentClock()).isInstanceOf(BUBBLE_CLOCK_CLASS); } @@ -133,7 +145,7 @@ public final class ClockManagerTest extends SysuiTestCase { // GIVEN that settings is set to the bubble clock face when(mMockSettingsWrapper.getLockScreenCustomClockFace(anyInt())).thenReturn(BUBBLE_CLOCK); // WHEN settings change event is fired - mContentObserver.onChange(false, SETTINGS_URI, USER_ID); + mContentObserver.onChange(false, SETTINGS_URI, MAIN_USER_ID); // THEN the plugin is the bubble clock face. ArgumentCaptor<ClockPlugin> captor = ArgumentCaptor.forClass(ClockPlugin.class); verify(mMockListener1).onClockChanged(captor.capture()); @@ -145,7 +157,7 @@ public final class ClockManagerTest extends SysuiTestCase { // GIVEN that settings is set to the bubble clock face when(mMockSettingsWrapper.getLockScreenCustomClockFace(anyInt())).thenReturn(BUBBLE_CLOCK); // WHEN settings change event is fired - mContentObserver.onChange(false, SETTINGS_URI, USER_ID); + mContentObserver.onChange(false, SETTINGS_URI, MAIN_USER_ID); // THEN the listeners receive separate instances of the Bubble clock plugin. ArgumentCaptor<ClockPlugin> captor1 = ArgumentCaptor.forClass(ClockPlugin.class); ArgumentCaptor<ClockPlugin> captor2 = ArgumentCaptor.forClass(ClockPlugin.class); @@ -162,7 +174,7 @@ public final class ClockManagerTest extends SysuiTestCase { // custom clock face. when(mMockSettingsWrapper.getLockScreenCustomClockFace(anyInt())).thenReturn("bad value"); // WHEN settings change event is fired - mContentObserver.onChange(false, SETTINGS_URI, USER_ID); + mContentObserver.onChange(false, SETTINGS_URI, MAIN_USER_ID); // THEN the result is null. assertThat(mClockManager.getCurrentClock()).isNull(); } @@ -206,4 +218,35 @@ public final class ClockManagerTest extends SysuiTestCase { // THEN the plugin is the bubble clock face. assertThat(mClockManager.getCurrentClock()).isInstanceOf(BUBBLE_CLOCK_CLASS); } + + @Test + public void onUserChanged_defaultClock() { + // WHEN the user changes + mCurrentUser.setValue(SECONDARY_USER_ID); + // THEN the plugin is null for the default clock face + assertThat(mClockManager.getCurrentClock()).isNull(); + } + + @Test + public void onUserChanged_customClock() { + // GIVEN that a second user has selected the bubble clock face + when(mMockSettingsWrapper.getLockScreenCustomClockFace(SECONDARY_USER_ID)).thenReturn( + BUBBLE_CLOCK); + // WHEN the user changes + mCurrentUser.setValue(SECONDARY_USER_ID); + // THEN the plugin is the bubble clock face. + assertThat(mClockManager.getCurrentClock()).isInstanceOf(BUBBLE_CLOCK_CLASS); + } + + @Test + public void onUserChanged_docked() { + // GIVEN device is docked + mFakeDockManager.setDockEvent(DockManager.STATE_DOCKED); + // AND the second user as selected the bubble clock for the dock + when(mMockSettingsWrapper.getDockedClockFace(SECONDARY_USER_ID)).thenReturn(BUBBLE_CLOCK); + // WHEN the user changes + mCurrentUser.setValue(SECONDARY_USER_ID); + // THEN the plugin is the bubble clock face. + assertThat(mClockManager.getCurrentClock()).isInstanceOf(BUBBLE_CLOCK_CLASS); + } } |