diff --git a/packages/SystemUI/res-keyguard/drawable/status_bar_user_chip_bg.xml b/packages/SystemUI/res-keyguard/drawable/status_bar_user_chip_bg.xml
new file mode 100644
index 0000000000000..989115697d6f2
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/drawable/status_bar_user_chip_bg.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index 850b017173084..e47eed9ea04a6 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -30,14 +30,39 @@
android:id="@+id/status_icon_area"
android:layout_width="wrap_content"
android:layout_height="match_parent"
+ android:layout_marginStart="@dimen/system_icons_super_container_margin_start"
android:paddingTop="@dimen/status_bar_padding_top"
android:layout_alignParentEnd="true"
android:gravity="center_vertical|end" >
+
+
+
+
+
+
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 8b244c757649c..af98019362070 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -119,6 +119,32 @@
android:gravity="center_vertical|end"
>
+
+
+
+
+
+
diff --git a/packages/SystemUI/res/layout/system_icons.xml b/packages/SystemUI/res/layout/system_icons.xml
index 6d5c7d40a5f82..4f4bae49b275b 100644
--- a/packages/SystemUI/res/layout/system_icons.xml
+++ b/packages/SystemUI/res/layout/system_icons.xml
@@ -17,7 +17,7 @@
diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml
index 2a70645e49ec0..49dd574af8298 100644
--- a/packages/SystemUI/res/values/flags.xml
+++ b/packages/SystemUI/res/values/flags.xml
@@ -32,4 +32,8 @@
false
+
+ false
+
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewModule.java
index fc14b6a99008a..8fc86004c400e 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewModule.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewModule.java
@@ -20,7 +20,11 @@ import com.android.keyguard.CarrierText;
import com.android.systemui.R;
import com.android.systemui.battery.BatteryMeterView;
import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
+import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer;
+import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherController;
+import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherControllerImpl;
+import dagger.Binds;
import dagger.Module;
import dagger.Provides;
@@ -39,4 +43,17 @@ public abstract class KeyguardStatusBarViewModule {
static BatteryMeterView getBatteryMeterView(KeyguardStatusBarView view) {
return view.findViewById(R.id.battery);
}
+
+ /** */
+ @Provides
+ @KeyguardStatusBarViewScope
+ static StatusBarUserSwitcherContainer getUserSwitcherContainer(KeyguardStatusBarView view) {
+ return view.findViewById(R.id.user_switcher_container);
+ }
+
+ /** */
+ @Binds
+ @KeyguardStatusBarViewScope
+ abstract StatusBarUserSwitcherController bindStatusBarUserSwitcherController(
+ StatusBarUserSwitcherControllerImpl controller);
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index c894b7023d756..d67815f485e03 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -112,8 +112,8 @@ public class Flags {
public static final BooleanFlag COMBINED_STATUS_BAR_SIGNAL_ICONS =
new BooleanFlag(601, false);
- public static final BooleanFlag STATUS_BAR_USER_SWITCHER =
- new BooleanFlag(602, false);
+ public static final ResourceBooleanFlag STATUS_BAR_USER_SWITCHER =
+ new ResourceBooleanFlag(602, R.bool.flag_user_switcher_chip);
/***************************************/
// 700 - dialer/calls
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 2ec5f250eb48c..b8e9875be7e22 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -40,6 +40,8 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
+import androidx.annotation.VisibleForTesting;
+
import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
@@ -67,8 +69,10 @@ public class KeyguardStatusBarView extends RelativeLayout {
private ImageView mMultiUserAvatar;
private BatteryMeterView mBatteryView;
private StatusIconContainer mStatusIconContainer;
+ private ViewGroup mUserSwitcherContainer;
private boolean mKeyguardUserSwitcherEnabled;
+ private boolean mKeyguardUserAvatarEnabled;
private boolean mIsPrivacyDotEnabled;
private int mSystemIconsSwitcherHiddenExpandedMargin;
@@ -111,10 +115,15 @@ public class KeyguardStatusBarView extends RelativeLayout {
mCutoutSpace = findViewById(R.id.cutout_space_view);
mStatusIconArea = findViewById(R.id.status_icon_area);
mStatusIconContainer = findViewById(R.id.statusIcons);
+ mUserSwitcherContainer = findViewById(R.id.user_switcher_container);
mIsPrivacyDotEnabled = mContext.getResources().getBoolean(R.bool.config_enablePrivacyDot);
loadDimens();
}
+ public ViewGroup getUserSwitcherContainer() {
+ return mUserSwitcherContainer;
+ }
+
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
@@ -186,6 +195,17 @@ public class KeyguardStatusBarView extends RelativeLayout {
}
private void updateVisibilities() {
+ // Multi user avatar is disabled in favor of the user switcher chip
+ if (!mKeyguardUserAvatarEnabled) {
+ if (mMultiUserAvatar.getParent() == mStatusIconArea) {
+ mStatusIconArea.removeView(mMultiUserAvatar);
+ } else if (mMultiUserAvatar.getParent() != null) {
+ getOverlay().remove(mMultiUserAvatar);
+ }
+
+ return;
+ }
+
if (mMultiUserAvatar.getParent() != mStatusIconArea
&& !mKeyguardUserSwitcherEnabled) {
if (mMultiUserAvatar.getParent() != null) {
@@ -346,6 +366,16 @@ public class KeyguardStatusBarView extends RelativeLayout {
mKeyguardUserSwitcherEnabled = enabled;
}
+ void setKeyguardUserAvatarEnabled(boolean enabled) {
+ mKeyguardUserAvatarEnabled = enabled;
+ updateVisibilities();
+ }
+
+ @VisibleForTesting
+ boolean isKeyguardUserAvatarEnabled() {
+ return mKeyguardUserAvatarEnabled;
+ }
+
private void animateNextLayoutChange() {
final int systemIconsCurrentX = mSystemIconsContainer.getLeft();
final boolean userAvatarVisible = mMultiUserAvatar.getParent() == mStatusIconArea;
@@ -416,9 +446,14 @@ public class KeyguardStatusBarView extends RelativeLayout {
/** Should only be called from {@link KeyguardStatusBarViewController}. */
void onOverlayChanged() {
- mCarrierLabel.setTextAppearance(
- Utils.getThemeAttr(mContext, com.android.internal.R.attr.textAppearanceSmall));
+ int theme = Utils.getThemeAttr(mContext, com.android.internal.R.attr.textAppearanceSmall);
+ mCarrierLabel.setTextAppearance(theme);
mBatteryView.updatePercentView();
+
+ TextView userSwitcherName = mUserSwitcherContainer.findViewById(R.id.current_user_name);
+ if (userSwitcherName != null) {
+ userSwitcherName.setTextAppearance(theme);
+ }
}
private void updateIconsAndTextColors(StatusBarIconController.TintedIconManager iconManager) {
@@ -429,6 +464,14 @@ public class KeyguardStatusBarView extends RelativeLayout {
R.color.light_mode_icon_color_single_tone);
float intensity = textColor == Color.WHITE ? 0 : 1;
mCarrierLabel.setTextColor(iconColor);
+
+ TextView userSwitcherName = mUserSwitcherContainer.findViewById(R.id.current_user_name);
+ if (userSwitcherName != null) {
+ userSwitcherName.setTextColor(Utils.getColorStateListDefaultColor(
+ mContext,
+ R.color.light_mode_icon_color_single_tone));
+ }
+
if (iconManager != null) {
iconManager.setTint(iconColor);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
index ee97fd6318189..1df1aff385939 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -47,6 +47,9 @@ import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
+import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserInfoTracker;
+import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherController;
+import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherFeatureController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -95,6 +98,9 @@ public class KeyguardStatusBarViewController extends ViewController mView.setKeyguardUserAvatarEnabled(!enabled));
}
@Override
@@ -293,6 +309,7 @@ public class KeyguardStatusBarViewController extends ViewController(view) {
@@ -89,6 +94,10 @@ class PhoneStatusBarViewController private constructor(
mView.setTouchEventHandler(touchEventHandler)
}
+ override fun onInit() {
+ userSwitcherController.init()
+ }
+
fun setImportantForAccessibility(mode: Int) {
mView.importantForAccessibility = mode
}
@@ -153,6 +162,7 @@ class PhoneStatusBarViewController private constructor(
private val unfoldComponent: Optional,
@Named(UNFOLD_STATUS_BAR)
private val progressProvider: Optional,
+ private val userSwitcherController: StatusBarUserSwitcherController,
private val configurationController: ConfigurationController
) {
fun create(
@@ -163,6 +173,7 @@ class PhoneStatusBarViewController private constructor(
view,
progressProvider.getOrNull(),
unfoldComponent.getOrNull()?.getStatusBarMoveFromCenterAnimationController(),
+ userSwitcherController,
touchEventHandler,
configurationController
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
index dea1b43f579f1..e2dc9057e49d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
@@ -26,11 +26,15 @@ import com.android.systemui.statusbar.phone.PhoneStatusBarTransitions;
import com.android.systemui.statusbar.phone.PhoneStatusBarView;
import com.android.systemui.statusbar.phone.PhoneStatusBarViewController;
import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
+import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer;
+import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherController;
+import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherControllerImpl;
import com.android.systemui.statusbar.policy.Clock;
import com.android.systemui.statusbar.window.StatusBarWindowController;
import javax.inject.Named;
+import dagger.Binds;
import dagger.Module;
import dagger.Provides;
@@ -80,6 +84,20 @@ public interface StatusBarFragmentModule {
return view.findViewById(R.id.clock);
}
+ /** */
+ @Provides
+ @StatusBarFragmentScope
+ static StatusBarUserSwitcherContainer provideStatusBarUserSwitcherContainer(
+ @RootView PhoneStatusBarView view) {
+ return view.findViewById(R.id.user_switcher_container);
+ }
+
+ /** */
+ @Binds
+ @StatusBarFragmentScope
+ StatusBarUserSwitcherController bindStatusBarUserSwitcherController(
+ StatusBarUserSwitcherControllerImpl controller);
+
/** */
@Provides
@StatusBarFragmentScope
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserInfoTracker.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserInfoTracker.kt
new file mode 100644
index 0000000000000..2dbc19c653f7b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserInfoTracker.kt
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2022 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.statusbar.phone.userswitcher
+
+import android.graphics.drawable.Drawable
+import android.os.UserManager
+
+import com.android.systemui.DejankUtils.whitelistIpcs
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.policy.CallbackController
+import com.android.systemui.statusbar.policy.UserInfoController
+import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener
+
+import javax.inject.Inject
+
+/**
+ * Since every user switcher chip will user the exact same information and logic on whether or not
+ * to show, and what data to show, it makes sense to create a single tracker here
+ */
+@SysUISingleton
+class StatusBarUserInfoTracker @Inject constructor(
+ private val userInfoController: UserInfoController,
+ private val userManager: UserManager
+) : CallbackController {
+ var currentUserName: String? = null
+ private set
+ var currentUserAvatar: Drawable? = null
+ private set
+ var userSwitcherEnabled = false
+ private set
+ private var listening = false
+
+ private val listeners = mutableListOf()
+
+ private val userInfoChangedListener = OnUserInfoChangedListener { name, picture, _ ->
+ currentUserAvatar = picture
+ currentUserName = name
+ notifyListenersUserInfoChanged()
+ }
+
+ init {
+ startListening()
+ }
+
+ override fun addCallback(listener: CurrentUserChipInfoUpdatedListener) {
+ if (listeners.isEmpty()) {
+ startListening()
+ }
+
+ if (!listeners.contains(listener)) {
+ listeners.add(listener)
+ }
+ }
+
+ override fun removeCallback(listener: CurrentUserChipInfoUpdatedListener) {
+ listeners.remove(listener)
+
+ if (listeners.isEmpty()) {
+ stopListening()
+ }
+ }
+
+ private fun notifyListenersUserInfoChanged() {
+ listeners.forEach {
+ it.onCurrentUserChipInfoUpdated()
+ }
+ }
+
+ private fun notifyListenersSettingChanged() {
+ listeners.forEach {
+ it.onStatusBarUserSwitcherSettingChanged(userSwitcherEnabled)
+ }
+ }
+
+ private fun startListening() {
+ listening = true
+ userInfoController.addCallback(userInfoChangedListener)
+ }
+
+ private fun stopListening() {
+ listening = false
+ userInfoController.removeCallback(userInfoChangedListener)
+ }
+
+ private fun checkUserSwitcherEnabled() {
+ whitelistIpcs {
+ userSwitcherEnabled = userManager.isUserSwitcherEnabled
+ }
+ }
+
+ /**
+ * Force a check to [UserManager.isUserSwitcherEnabled], and update listeners if the value has
+ * changed
+ */
+ fun checkEnabled() {
+ val wasEnabled = userSwitcherEnabled
+ checkUserSwitcherEnabled()
+
+ if (wasEnabled != userSwitcherEnabled) {
+ notifyListenersSettingChanged()
+ }
+ }
+}
+
+interface CurrentUserChipInfoUpdatedListener {
+ fun onCurrentUserChipInfoUpdated()
+ fun onStatusBarUserSwitcherSettingChanged(enabled: Boolean) {}
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherContainer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherContainer.kt
new file mode 100644
index 0000000000000..2c8677dee4d9c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherContainer.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 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.statusbar.phone.userswitcher
+
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.TextView
+import com.android.systemui.R
+
+class StatusBarUserSwitcherContainer(
+ context: Context?,
+ attrs: AttributeSet?
+) : LinearLayout(context, attrs) {
+ lateinit var text: TextView
+ private set
+ lateinit var avatar: ImageView
+ private set
+
+ override fun onFinishInflate() {
+ super.onFinishInflate()
+ text = findViewById(R.id.current_user_name)
+ avatar = findViewById(R.id.current_user_avatar)
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt
new file mode 100644
index 0000000000000..a1247539c6605
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2022 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.statusbar.phone.userswitcher
+
+import android.view.View
+
+import com.android.systemui.qs.user.UserSwitchDialogController
+import com.android.systemui.util.ViewController
+
+import javax.inject.Inject
+
+/**
+ * ViewController for [StatusBarUserSwitcherContainer]
+ */
+class StatusBarUserSwitcherControllerImpl @Inject constructor(
+ view: StatusBarUserSwitcherContainer,
+ private val tracker: StatusBarUserInfoTracker,
+ private val featureController: StatusBarUserSwitcherFeatureController,
+ private val userSwitcherDialogController: UserSwitchDialogController
+) : ViewController(view),
+ StatusBarUserSwitcherController {
+ private val listener = object : CurrentUserChipInfoUpdatedListener {
+ override fun onCurrentUserChipInfoUpdated() {
+ updateChip()
+ }
+
+ override fun onStatusBarUserSwitcherSettingChanged(enabled: Boolean) {
+ updateEnabled()
+ }
+ }
+
+ private val featureFlagListener = object : OnUserSwitcherPreferenceChangeListener {
+ override fun onUserSwitcherPreferenceChange(enabled: Boolean) {
+ updateEnabled()
+ }
+ }
+
+ override fun onViewAttached() {
+ tracker.addCallback(listener)
+ featureController.addCallback(featureFlagListener)
+ mView.setOnClickListener {
+ userSwitcherDialogController.showDialog(it)
+ }
+
+ updateEnabled()
+ }
+
+ override fun onViewDetached() {
+ tracker.removeCallback(listener)
+ featureController.removeCallback(featureFlagListener)
+ mView.setOnClickListener(null)
+ }
+
+ private fun updateChip() {
+ mView.text.text = tracker.currentUserName
+ mView.avatar.setImageDrawable(tracker.currentUserAvatar)
+ }
+
+ private fun updateEnabled() {
+ if (featureController.isStatusBarUserSwitcherFeatureEnabled() &&
+ tracker.userSwitcherEnabled) {
+ mView.visibility = View.VISIBLE
+ updateChip()
+ } else {
+ mView.visibility = View.GONE
+ }
+ }
+}
+
+interface StatusBarUserSwitcherController {
+ fun init()
+}
+
+private const val TAG = "SbUserSwitcherController"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherFeatureController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherFeatureController.kt
new file mode 100644
index 0000000000000..7bae9ff727603
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherFeatureController.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2022 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.statusbar.phone.userswitcher
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.statusbar.policy.CallbackController
+
+import javax.inject.Inject
+
+@SysUISingleton
+class StatusBarUserSwitcherFeatureController @Inject constructor(
+ private val flags: FeatureFlags
+) : CallbackController {
+ private val listeners = mutableListOf()
+
+ init {
+ flags.addListener(Flags.STATUS_BAR_USER_SWITCHER) {
+ it.requestNoRestart()
+ notifyListeners()
+ }
+ }
+
+ fun isStatusBarUserSwitcherFeatureEnabled(): Boolean {
+ return flags.isEnabled(Flags.STATUS_BAR_USER_SWITCHER)
+ }
+
+ override fun addCallback(listener: OnUserSwitcherPreferenceChangeListener) {
+ if (!listeners.contains(listener)) {
+ listeners.add(listener)
+ }
+ }
+
+ override fun removeCallback(listener: OnUserSwitcherPreferenceChangeListener) {
+ listeners.remove(listener)
+ }
+
+ private fun notifyListeners() {
+ val enabled = flags.isEnabled(Flags.STATUS_BAR_USER_SWITCHER)
+ listeners.forEach {
+ it.onUserSwitcherPreferenceChange(enabled)
+ }
+ }
+}
+
+interface OnUserSwitcherPreferenceChangeListener {
+ fun onUserSwitcherPreferenceChange(enabled: Boolean)
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
index 01e9822e0484d..7de35458a893d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
@@ -47,6 +47,9 @@ import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
+import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserInfoTracker;
+import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherController;
+import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherFeatureController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -99,6 +102,12 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
private ArgumentCaptor mConfigurationListenerCaptor;
@Captor
private ArgumentCaptor mKeyguardCallbackCaptor;
+ @Mock
+ private StatusBarUserSwitcherFeatureController mStatusBarUserSwitcherFeatureController;
+ @Mock
+ private StatusBarUserSwitcherController mStatusBarUserSwitcherController;
+ @Mock
+ private StatusBarUserInfoTracker mStatusBarUserInfoTracker;
private TestNotificationPanelViewStateProvider mNotificationPanelViewStateProvider;
private KeyguardStatusBarView mKeyguardStatusBarView;
@@ -117,7 +126,11 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
.inflate(R.layout.keyguard_status_bar, null));
});
- mController = new KeyguardStatusBarViewController(
+ mController = createController();
+ }
+
+ private KeyguardStatusBarViewController createController() {
+ return new KeyguardStatusBarViewController(
mKeyguardStatusBarView,
mCarrierTextController,
mConfigurationController,
@@ -134,7 +147,10 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
mBiometricUnlockController,
mStatusBarStateController,
mStatusBarContentInsetsProvider,
- mUserManager
+ mUserManager,
+ mStatusBarUserSwitcherFeatureController,
+ mStatusBarUserSwitcherController,
+ mStatusBarUserInfoTracker
);
}
@@ -356,6 +372,32 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.VISIBLE);
}
+ @Test
+ public void testNewUserSwitcherDisablesAvatar_newUiOn() {
+ // GIVEN the status bar user switcher chip is enabled
+ when(mStatusBarUserSwitcherFeatureController.isStatusBarUserSwitcherFeatureEnabled())
+ .thenReturn(true);
+
+ // WHEN the controller is created
+ mController = createController();
+
+ // THEN keyguard status bar view avatar is disabled
+ assertThat(mKeyguardStatusBarView.isKeyguardUserAvatarEnabled()).isFalse();
+ }
+
+ @Test
+ public void testNewUserSwitcherDisablesAvatar_newUiOff() {
+ // GIVEN the status bar user switcher chip is disabled
+ when(mStatusBarUserSwitcherFeatureController.isStatusBarUserSwitcherFeatureEnabled())
+ .thenReturn(false);
+
+ // WHEN the controller is created
+ mController = createController();
+
+ // THEN keyguard status bar view avatar is enabled
+ assertThat(mKeyguardStatusBarView.isKeyguardUserAvatarEnabled()).isTrue();
+ }
+
private void updateStateToNotKeyguard() {
updateStatusBarState(SHADE);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
index c65a6b6cde1af..5891161847103 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -26,6 +26,7 @@ import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.unfold.SysUIUnfoldComponent
import com.android.systemui.unfold.config.UnfoldTransitionConfig
@@ -60,6 +61,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
private lateinit var progressProvider: ScopedUnfoldTransitionProgressProvider
@Mock
private lateinit var configurationController: ConfigurationController
+ @Mock
+ private lateinit var userSwitcherController: StatusBarUserSwitcherController
private lateinit var view: PhoneStatusBarView
private lateinit var controller: PhoneStatusBarViewController
@@ -187,6 +190,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
return PhoneStatusBarViewController.Factory(
Optional.of(sysuiUnfoldComponent),
Optional.of(progressProvider),
+ userSwitcherController,
configurationController
).create(view, touchEventHandler).also {
it.init()