Loading packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java +4 −0 Original line number Diff line number Diff line Loading @@ -176,6 +176,10 @@ public class UserIconDrawable extends Drawable implements Drawable.Callback { return this; } public boolean isEmpty() { return getUserIcon() == null && getUserDrawable() == null; } public UserIconDrawable setBadge(Drawable badge) { mBadge = badge; if (mBadge != null) { Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java +4 −0 Original line number Diff line number Diff line Loading @@ -137,4 +137,8 @@ public class UserAvatarView extends View { mDrawable.setIconDrawable(d); mDrawable.setBadgeIfManagedUser(getContext(), userId); } public boolean isEmpty() { return mDrawable.isEmpty(); } } packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java +77 −31 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.UiEventLogger; import com.android.keyguard.KeyguardConstants; import com.android.keyguard.KeyguardVisibilityHelper; Loading @@ -36,7 +37,6 @@ import com.android.keyguard.dagger.KeyguardUserSwitcherScope; import com.android.settingslib.drawable.CircleFramedDrawable; import com.android.systemui.R; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.user.UserSwitchDialogController; Loading Loading @@ -68,7 +68,6 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> private final Context mContext; private Resources mResources; private final UserSwitcherController mUserSwitcherController; private final ScreenLifecycle mScreenLifecycle; private UserSwitcherController.BaseUserAdapter mAdapter; private final KeyguardStateController mKeyguardStateController; private final FalsingManager mFalsingManager; Loading @@ -77,8 +76,10 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> private final KeyguardVisibilityHelper mKeyguardVisibilityHelper; private final UserSwitchDialogController mUserSwitchDialogController; private final UiEventLogger mUiEventLogger; private UserAvatarView mUserAvatarView; @VisibleForTesting UserAvatarView mUserAvatarView; UserSwitcherController.UserRecord mCurrentUser; private boolean mIsKeyguardShowing; // State info for the user switch and keyguard private int mBarState; Loading @@ -87,8 +88,6 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> new StatusBarStateController.StateListener() { @Override public void onStateChanged(int newState) { if (DEBUG) Log.d(TAG, String.format("onStateChanged: newState=%d", newState)); boolean goingToFullShade = mStatusBarStateController.goingToFullShade(); boolean keyguardFadingAway = mKeyguardStateController.isKeyguardFadingAway(); int oldState = mBarState; Loading @@ -102,12 +101,34 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> } }; private ConfigurationController.ConfigurationListener mConfigurationListener = new ConfigurationController.ConfigurationListener() { private ConfigurationController.ConfigurationListener mConfigurationListener = new ConfigurationController.ConfigurationListener() { @Override public void onUiModeChanged() { updateView(true); // Force update when dark theme toggled. Otherwise, icon will not update // until it is clicked if (mIsKeyguardShowing) { updateView(); } } }; private final KeyguardStateController.Callback mKeyguardStateCallback = new KeyguardStateController.Callback() { @Override public void onUnlockedChanged() { updateKeyguardShowing(false /* forceViewUpdate */); } @Override public void onKeyguardShowingChanged() { updateKeyguardShowing(false /* forceViewUpdate */); } @Override public void onKeyguardFadingAwayChanged() { updateKeyguardShowing(false /* forceViewUpdate */); } }; Loading @@ -116,7 +137,6 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> FrameLayout view, Context context, @Main Resources resources, ScreenLifecycle screenLifecycle, UserSwitcherController userSwitcherController, KeyguardStateController keyguardStateController, FalsingManager falsingManager, Loading @@ -130,7 +150,6 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> if (DEBUG) Log.d(TAG, "New KeyguardQsUserSwitchController"); mContext = context; mResources = resources; mScreenLifecycle = screenLifecycle; mUserSwitcherController = userSwitcherController; mKeyguardStateController = keyguardStateController; mFalsingManager = falsingManager; Loading Loading @@ -188,7 +207,10 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> mDataSetObserver.onChanged(); mStatusBarStateController.addCallback(mStatusBarStateListener); mConfigurationController.addCallback(mConfigurationListener); updateView(true /* forceUpdate */); mKeyguardStateController.addCallback(mKeyguardStateCallback); // Force update when view attached in case configuration changed while the view was detached updateCurrentUser(); updateKeyguardShowing(true /* forceViewUpdate */); } @Override Loading @@ -198,15 +220,48 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> mAdapter.unregisterDataSetObserver(mDataSetObserver); mStatusBarStateController.removeCallback(mStatusBarStateListener); mConfigurationController.removeCallback(mConfigurationListener); mKeyguardStateController.removeCallback(mKeyguardStateCallback); } public final DataSetObserver mDataSetObserver = new DataSetObserver() { @Override public void onChanged() { updateView(false /* forceUpdate */); boolean userChanged = updateCurrentUser(); if (userChanged || (mIsKeyguardShowing && mUserAvatarView.isEmpty())) { updateView(); } } }; private void clearAvatar() { if (DEBUG) Log.d(TAG, "clearAvatar"); mUserAvatarView.setAvatar(null); } /** * @param forceViewUpdate whether view should be updated regardless of whether * keyguard-showing state changed */ @VisibleForTesting void updateKeyguardShowing(boolean forceViewUpdate) { boolean wasKeyguardShowing = mIsKeyguardShowing; mIsKeyguardShowing = mKeyguardStateController.isShowing() || mKeyguardStateController.isKeyguardGoingAway(); if (wasKeyguardShowing == mIsKeyguardShowing && !forceViewUpdate) { return; } if (DEBUG) { Log.d(TAG, "updateKeyguardShowing:" + " mIsKeyguardShowing=" + mIsKeyguardShowing + " forceViewUpdate=" + forceViewUpdate); } if (mIsKeyguardShowing) { updateView(); } else { clearAvatar(); } } /** * @return true if the current user has changed */ Loading @@ -223,31 +278,22 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> return mCurrentUser == null && previousUser != null; } /** * @param forceUpdate whether to update view even if current user did not change */ private void updateView(boolean forceUpdate) { if (!updateCurrentUser() && !forceUpdate) { return; } String contentDescription = null; if (mCurrentUser != null && mCurrentUser.info != null && !TextUtils.isEmpty( mCurrentUser.info.name)) { private String getContentDescription() { if (mCurrentUser != null && mCurrentUser.info != null && !TextUtils.isEmpty(mCurrentUser.info.name)) { // If we know the current user's name, have TalkBack to announce "Signed in as [user // name]" when the icon is selected contentDescription = mContext.getString(R.string.accessibility_quick_settings_user, mCurrentUser.info.name); return mContext.getString( R.string.accessibility_quick_settings_user, mCurrentUser.info.name); } else { // As a fallback, have TalkBack announce "Switch user" contentDescription = mContext.getString( R.string.accessibility_multi_user_switch_switcher); return mContext.getString(R.string.accessibility_multi_user_switch_switcher); } if (!TextUtils.equals(mUserAvatarView.getContentDescription(), contentDescription)) { mUserAvatarView.setContentDescription(contentDescription); } private void updateView() { if (DEBUG) Log.d(TAG, "updateView"); mUserAvatarView.setContentDescription(getContentDescription()); int userId = mCurrentUser != null ? mCurrentUser.resolveId() : UserHandle.USER_NULL; mUserAvatarView.setDrawableWithBadge(getCurrentUserIcon().mutate(), userId); } Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt +27 −5 Original line number Diff line number Diff line Loading @@ -26,13 +26,13 @@ import androidx.test.filters.SmallTest import com.android.internal.logging.UiEventLogger import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.keyguard.ScreenLifecycle import com.android.systemui.plugins.FalsingManager import com.android.systemui.qs.user.UserSwitchDialogController import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.phone.LockscreenGestureLogger import com.android.systemui.statusbar.phone.ScreenOffAnimationController import com.google.common.truth.Truth.assertThat import org.junit.After import org.junit.Before import org.junit.Test Loading @@ -47,9 +47,6 @@ import org.mockito.MockitoAnnotations @TestableLooper.RunWithLooper @RunWith(AndroidTestingRunner::class) class KeyguardQsUserSwitchControllerTest : SysuiTestCase() { @Mock private lateinit var screenLifecycle: ScreenLifecycle @Mock private lateinit var userSwitcherController: UserSwitcherController Loading Loading @@ -93,7 +90,6 @@ class KeyguardQsUserSwitchControllerTest : SysuiTestCase() { view, context, context.resources, screenLifecycle, userSwitcherController, keyguardStateController, falsingManager, Loading @@ -108,6 +104,8 @@ class KeyguardQsUserSwitchControllerTest : SysuiTestCase() { testableLooper.processAllMessages() `when`(userSwitcherController.keyguardStateController).thenReturn(keyguardStateController) `when`(userSwitcherController.keyguardStateController.isShowing).thenReturn(true) `when`(keyguardStateController.isShowing).thenReturn(true) `when`(keyguardStateController.isKeyguardGoingAway).thenReturn(false) keyguardQsUserSwitchController.init() } Loading @@ -122,4 +120,28 @@ class KeyguardQsUserSwitchControllerTest : SysuiTestCase() { verify(uiEventLogger, times(1)) .log(LockscreenGestureLogger.LockscreenUiEvent.LOCKSCREEN_SWITCH_USER_TAP) } @Test fun testAvatarExistsWhenKeyguardGoingAway() { `when`(keyguardStateController.isShowing).thenReturn(false) `when`(keyguardStateController.isKeyguardGoingAway).thenReturn(true) keyguardQsUserSwitchController.updateKeyguardShowing(true /* forceViewUpdate */) assertThat(keyguardQsUserSwitchController.mUserAvatarView.isEmpty).isFalse() } @Test fun testAvatarExistsWhenKeyguardShown() { `when`(keyguardStateController.isShowing).thenReturn(true) `when`(keyguardStateController.isKeyguardGoingAway).thenReturn(false) keyguardQsUserSwitchController.updateKeyguardShowing(true /* forceViewUpdate */) assertThat(keyguardQsUserSwitchController.mUserAvatarView.isEmpty).isFalse() } @Test fun testAvatarGoneWhenKeyguardGone() { `when`(keyguardStateController.isShowing).thenReturn(false) `when`(keyguardStateController.isKeyguardGoingAway).thenReturn(false) keyguardQsUserSwitchController.updateKeyguardShowing(true /* forceViewUpdate */) assertThat(keyguardQsUserSwitchController.mUserAvatarView.isEmpty).isTrue() } } Loading
packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java +4 −0 Original line number Diff line number Diff line Loading @@ -176,6 +176,10 @@ public class UserIconDrawable extends Drawable implements Drawable.Callback { return this; } public boolean isEmpty() { return getUserIcon() == null && getUserDrawable() == null; } public UserIconDrawable setBadge(Drawable badge) { mBadge = badge; if (mBadge != null) { Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java +4 −0 Original line number Diff line number Diff line Loading @@ -137,4 +137,8 @@ public class UserAvatarView extends View { mDrawable.setIconDrawable(d); mDrawable.setBadgeIfManagedUser(getContext(), userId); } public boolean isEmpty() { return mDrawable.isEmpty(); } }
packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java +77 −31 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.UiEventLogger; import com.android.keyguard.KeyguardConstants; import com.android.keyguard.KeyguardVisibilityHelper; Loading @@ -36,7 +37,6 @@ import com.android.keyguard.dagger.KeyguardUserSwitcherScope; import com.android.settingslib.drawable.CircleFramedDrawable; import com.android.systemui.R; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.user.UserSwitchDialogController; Loading Loading @@ -68,7 +68,6 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> private final Context mContext; private Resources mResources; private final UserSwitcherController mUserSwitcherController; private final ScreenLifecycle mScreenLifecycle; private UserSwitcherController.BaseUserAdapter mAdapter; private final KeyguardStateController mKeyguardStateController; private final FalsingManager mFalsingManager; Loading @@ -77,8 +76,10 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> private final KeyguardVisibilityHelper mKeyguardVisibilityHelper; private final UserSwitchDialogController mUserSwitchDialogController; private final UiEventLogger mUiEventLogger; private UserAvatarView mUserAvatarView; @VisibleForTesting UserAvatarView mUserAvatarView; UserSwitcherController.UserRecord mCurrentUser; private boolean mIsKeyguardShowing; // State info for the user switch and keyguard private int mBarState; Loading @@ -87,8 +88,6 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> new StatusBarStateController.StateListener() { @Override public void onStateChanged(int newState) { if (DEBUG) Log.d(TAG, String.format("onStateChanged: newState=%d", newState)); boolean goingToFullShade = mStatusBarStateController.goingToFullShade(); boolean keyguardFadingAway = mKeyguardStateController.isKeyguardFadingAway(); int oldState = mBarState; Loading @@ -102,12 +101,34 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> } }; private ConfigurationController.ConfigurationListener mConfigurationListener = new ConfigurationController.ConfigurationListener() { private ConfigurationController.ConfigurationListener mConfigurationListener = new ConfigurationController.ConfigurationListener() { @Override public void onUiModeChanged() { updateView(true); // Force update when dark theme toggled. Otherwise, icon will not update // until it is clicked if (mIsKeyguardShowing) { updateView(); } } }; private final KeyguardStateController.Callback mKeyguardStateCallback = new KeyguardStateController.Callback() { @Override public void onUnlockedChanged() { updateKeyguardShowing(false /* forceViewUpdate */); } @Override public void onKeyguardShowingChanged() { updateKeyguardShowing(false /* forceViewUpdate */); } @Override public void onKeyguardFadingAwayChanged() { updateKeyguardShowing(false /* forceViewUpdate */); } }; Loading @@ -116,7 +137,6 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> FrameLayout view, Context context, @Main Resources resources, ScreenLifecycle screenLifecycle, UserSwitcherController userSwitcherController, KeyguardStateController keyguardStateController, FalsingManager falsingManager, Loading @@ -130,7 +150,6 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> if (DEBUG) Log.d(TAG, "New KeyguardQsUserSwitchController"); mContext = context; mResources = resources; mScreenLifecycle = screenLifecycle; mUserSwitcherController = userSwitcherController; mKeyguardStateController = keyguardStateController; mFalsingManager = falsingManager; Loading Loading @@ -188,7 +207,10 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> mDataSetObserver.onChanged(); mStatusBarStateController.addCallback(mStatusBarStateListener); mConfigurationController.addCallback(mConfigurationListener); updateView(true /* forceUpdate */); mKeyguardStateController.addCallback(mKeyguardStateCallback); // Force update when view attached in case configuration changed while the view was detached updateCurrentUser(); updateKeyguardShowing(true /* forceViewUpdate */); } @Override Loading @@ -198,15 +220,48 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> mAdapter.unregisterDataSetObserver(mDataSetObserver); mStatusBarStateController.removeCallback(mStatusBarStateListener); mConfigurationController.removeCallback(mConfigurationListener); mKeyguardStateController.removeCallback(mKeyguardStateCallback); } public final DataSetObserver mDataSetObserver = new DataSetObserver() { @Override public void onChanged() { updateView(false /* forceUpdate */); boolean userChanged = updateCurrentUser(); if (userChanged || (mIsKeyguardShowing && mUserAvatarView.isEmpty())) { updateView(); } } }; private void clearAvatar() { if (DEBUG) Log.d(TAG, "clearAvatar"); mUserAvatarView.setAvatar(null); } /** * @param forceViewUpdate whether view should be updated regardless of whether * keyguard-showing state changed */ @VisibleForTesting void updateKeyguardShowing(boolean forceViewUpdate) { boolean wasKeyguardShowing = mIsKeyguardShowing; mIsKeyguardShowing = mKeyguardStateController.isShowing() || mKeyguardStateController.isKeyguardGoingAway(); if (wasKeyguardShowing == mIsKeyguardShowing && !forceViewUpdate) { return; } if (DEBUG) { Log.d(TAG, "updateKeyguardShowing:" + " mIsKeyguardShowing=" + mIsKeyguardShowing + " forceViewUpdate=" + forceViewUpdate); } if (mIsKeyguardShowing) { updateView(); } else { clearAvatar(); } } /** * @return true if the current user has changed */ Loading @@ -223,31 +278,22 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> return mCurrentUser == null && previousUser != null; } /** * @param forceUpdate whether to update view even if current user did not change */ private void updateView(boolean forceUpdate) { if (!updateCurrentUser() && !forceUpdate) { return; } String contentDescription = null; if (mCurrentUser != null && mCurrentUser.info != null && !TextUtils.isEmpty( mCurrentUser.info.name)) { private String getContentDescription() { if (mCurrentUser != null && mCurrentUser.info != null && !TextUtils.isEmpty(mCurrentUser.info.name)) { // If we know the current user's name, have TalkBack to announce "Signed in as [user // name]" when the icon is selected contentDescription = mContext.getString(R.string.accessibility_quick_settings_user, mCurrentUser.info.name); return mContext.getString( R.string.accessibility_quick_settings_user, mCurrentUser.info.name); } else { // As a fallback, have TalkBack announce "Switch user" contentDescription = mContext.getString( R.string.accessibility_multi_user_switch_switcher); return mContext.getString(R.string.accessibility_multi_user_switch_switcher); } if (!TextUtils.equals(mUserAvatarView.getContentDescription(), contentDescription)) { mUserAvatarView.setContentDescription(contentDescription); } private void updateView() { if (DEBUG) Log.d(TAG, "updateView"); mUserAvatarView.setContentDescription(getContentDescription()); int userId = mCurrentUser != null ? mCurrentUser.resolveId() : UserHandle.USER_NULL; mUserAvatarView.setDrawableWithBadge(getCurrentUserIcon().mutate(), userId); } Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt +27 −5 Original line number Diff line number Diff line Loading @@ -26,13 +26,13 @@ import androidx.test.filters.SmallTest import com.android.internal.logging.UiEventLogger import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.keyguard.ScreenLifecycle import com.android.systemui.plugins.FalsingManager import com.android.systemui.qs.user.UserSwitchDialogController import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.phone.DozeParameters import com.android.systemui.statusbar.phone.LockscreenGestureLogger import com.android.systemui.statusbar.phone.ScreenOffAnimationController import com.google.common.truth.Truth.assertThat import org.junit.After import org.junit.Before import org.junit.Test Loading @@ -47,9 +47,6 @@ import org.mockito.MockitoAnnotations @TestableLooper.RunWithLooper @RunWith(AndroidTestingRunner::class) class KeyguardQsUserSwitchControllerTest : SysuiTestCase() { @Mock private lateinit var screenLifecycle: ScreenLifecycle @Mock private lateinit var userSwitcherController: UserSwitcherController Loading Loading @@ -93,7 +90,6 @@ class KeyguardQsUserSwitchControllerTest : SysuiTestCase() { view, context, context.resources, screenLifecycle, userSwitcherController, keyguardStateController, falsingManager, Loading @@ -108,6 +104,8 @@ class KeyguardQsUserSwitchControllerTest : SysuiTestCase() { testableLooper.processAllMessages() `when`(userSwitcherController.keyguardStateController).thenReturn(keyguardStateController) `when`(userSwitcherController.keyguardStateController.isShowing).thenReturn(true) `when`(keyguardStateController.isShowing).thenReturn(true) `when`(keyguardStateController.isKeyguardGoingAway).thenReturn(false) keyguardQsUserSwitchController.init() } Loading @@ -122,4 +120,28 @@ class KeyguardQsUserSwitchControllerTest : SysuiTestCase() { verify(uiEventLogger, times(1)) .log(LockscreenGestureLogger.LockscreenUiEvent.LOCKSCREEN_SWITCH_USER_TAP) } @Test fun testAvatarExistsWhenKeyguardGoingAway() { `when`(keyguardStateController.isShowing).thenReturn(false) `when`(keyguardStateController.isKeyguardGoingAway).thenReturn(true) keyguardQsUserSwitchController.updateKeyguardShowing(true /* forceViewUpdate */) assertThat(keyguardQsUserSwitchController.mUserAvatarView.isEmpty).isFalse() } @Test fun testAvatarExistsWhenKeyguardShown() { `when`(keyguardStateController.isShowing).thenReturn(true) `when`(keyguardStateController.isKeyguardGoingAway).thenReturn(false) keyguardQsUserSwitchController.updateKeyguardShowing(true /* forceViewUpdate */) assertThat(keyguardQsUserSwitchController.mUserAvatarView.isEmpty).isFalse() } @Test fun testAvatarGoneWhenKeyguardGone() { `when`(keyguardStateController.isShowing).thenReturn(false) `when`(keyguardStateController.isKeyguardGoingAway).thenReturn(false) keyguardQsUserSwitchController.updateKeyguardShowing(true /* forceViewUpdate */) assertThat(keyguardQsUserSwitchController.mUserAvatarView.isEmpty).isTrue() } }