Merge changes I8d766f4a,I3f5e212f,Ia78513a0 into tm-qpr-dev
* changes: Update status bar user chip view spec Replace StatusBarUserSwitcherController with UserInteractor Move showUserSwitcher to UserInteractor
This commit is contained in:
@@ -34,30 +34,13 @@
|
|||||||
android:paddingTop="@dimen/status_bar_padding_top"
|
android:paddingTop="@dimen/status_bar_padding_top"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:gravity="center_vertical|end" >
|
android:gravity="center_vertical|end" >
|
||||||
<com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer
|
|
||||||
|
<include
|
||||||
android:id="@+id/user_switcher_container"
|
android:id="@+id/user_switcher_container"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center"
|
android:layout_marginEnd="@dimen/status_bar_user_chip_end_margin"
|
||||||
android:orientation="horizontal"
|
layout="@layout/status_bar_user_chip_container" />
|
||||||
android:paddingTop="4dp"
|
|
||||||
android:paddingBottom="4dp"
|
|
||||||
android:paddingStart="8dp"
|
|
||||||
android:paddingEnd="8dp"
|
|
||||||
android:background="@drawable/status_bar_user_chip_bg"
|
|
||||||
android:visibility="visible" >
|
|
||||||
<ImageView android:id="@+id/current_user_avatar"
|
|
||||||
android:layout_width="@dimen/multi_user_avatar_keyguard_size"
|
|
||||||
android:layout_height="@dimen/multi_user_avatar_keyguard_size"
|
|
||||||
android:scaleType="centerInside"
|
|
||||||
android:paddingEnd="4dp" />
|
|
||||||
|
|
||||||
<TextView android:id="@+id/current_user_name"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="@style/TextAppearance.StatusBar.Clock"
|
|
||||||
/>
|
|
||||||
</com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer>
|
|
||||||
|
|
||||||
<FrameLayout android:id="@+id/system_icons_container"
|
<FrameLayout android:id="@+id/system_icons_container"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|||||||
@@ -136,31 +136,12 @@
|
|||||||
android:gravity="center_vertical|end"
|
android:gravity="center_vertical|end"
|
||||||
android:clipChildren="false">
|
android:clipChildren="false">
|
||||||
|
|
||||||
<com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer
|
<include
|
||||||
android:id="@+id/user_switcher_container"
|
android:id="@+id/user_switcher_container"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center"
|
android:layout_marginEnd="@dimen/status_bar_user_chip_end_margin"
|
||||||
android:orientation="horizontal"
|
layout="@layout/status_bar_user_chip_container" />
|
||||||
android:paddingTop="4dp"
|
|
||||||
android:paddingBottom="4dp"
|
|
||||||
android:paddingStart="8dp"
|
|
||||||
android:paddingEnd="8dp"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:background="@drawable/status_bar_user_chip_bg"
|
|
||||||
android:visibility="visible" >
|
|
||||||
<ImageView android:id="@+id/current_user_avatar"
|
|
||||||
android:layout_width="@dimen/multi_user_avatar_keyguard_size"
|
|
||||||
android:layout_height="@dimen/multi_user_avatar_keyguard_size"
|
|
||||||
android:scaleType="centerInside"
|
|
||||||
android:paddingEnd="4dp" />
|
|
||||||
|
|
||||||
<TextView android:id="@+id/current_user_name"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="@style/TextAppearance.StatusBar.Clock"
|
|
||||||
/>
|
|
||||||
</com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer>
|
|
||||||
|
|
||||||
<include layout="@layout/system_icons" />
|
<include layout="@layout/system_icons" />
|
||||||
</com.android.keyguard.AlphaOptimizedLinearLayout>
|
</com.android.keyguard.AlphaOptimizedLinearLayout>
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/user_switcher_container"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginEnd="@dimen/status_bar_user_chip_end_margin"
|
||||||
|
android:background="@drawable/status_bar_user_chip_bg"
|
||||||
|
android:visibility="visible" >
|
||||||
|
<ImageView android:id="@+id/current_user_avatar"
|
||||||
|
android:layout_width="@dimen/status_bar_user_chip_avatar_size"
|
||||||
|
android:layout_height="@dimen/status_bar_user_chip_avatar_size"
|
||||||
|
android:layout_margin="4dp"
|
||||||
|
android:scaleType="centerInside" />
|
||||||
|
|
||||||
|
<TextView android:id="@+id/current_user_name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingEnd="8dp"
|
||||||
|
android:textAppearance="@style/TextAppearance.StatusBar.UserChip"
|
||||||
|
/>
|
||||||
|
</com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer>
|
||||||
@@ -1404,6 +1404,11 @@
|
|||||||
<dimen name="ongoing_call_chip_icon_text_padding">4dp</dimen>
|
<dimen name="ongoing_call_chip_icon_text_padding">4dp</dimen>
|
||||||
<dimen name="ongoing_call_chip_corner_radius">28dp</dimen>
|
<dimen name="ongoing_call_chip_corner_radius">28dp</dimen>
|
||||||
|
|
||||||
|
<!-- Status bar user chip -->
|
||||||
|
<dimen name="status_bar_user_chip_avatar_size">16dp</dimen>
|
||||||
|
<dimen name="status_bar_user_chip_end_margin">12dp</dimen>
|
||||||
|
<dimen name="status_bar_user_chip_text_size">12sp</dimen>
|
||||||
|
|
||||||
<!-- Internet panel related dimensions -->
|
<!-- Internet panel related dimensions -->
|
||||||
<dimen name="internet_dialog_list_max_height">662dp</dimen>
|
<dimen name="internet_dialog_list_max_height">662dp</dimen>
|
||||||
<!-- The height of the WiFi network in Internet panel. -->
|
<!-- The height of the WiFi network in Internet panel. -->
|
||||||
|
|||||||
@@ -23,6 +23,12 @@
|
|||||||
<item name="android:textColor">@color/status_bar_clock_color</item>
|
<item name="android:textColor">@color/status_bar_clock_color</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="TextAppearance.StatusBar.UserChip" parent="@*android:style/TextAppearance.StatusBar.Icon">
|
||||||
|
<item name="android:textSize">@dimen/status_bar_user_chip_text_size</item>
|
||||||
|
<item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
|
||||||
|
<item name="android:textColor">@color/status_bar_clock_color</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="TextAppearance.StatusBar.Expanded" parent="@*android:style/TextAppearance.StatusBar">
|
<style name="TextAppearance.StatusBar.Expanded" parent="@*android:style/TextAppearance.StatusBar">
|
||||||
<item name="android:textColor">?android:attr/textColorTertiary</item>
|
<item name="android:textColor">?android:attr/textColorTertiary</item>
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -21,10 +21,7 @@ import com.android.systemui.R;
|
|||||||
import com.android.systemui.battery.BatteryMeterView;
|
import com.android.systemui.battery.BatteryMeterView;
|
||||||
import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
|
import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
|
||||||
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer;
|
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.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
|
|
||||||
@@ -50,10 +47,4 @@ public abstract class KeyguardStatusBarViewModule {
|
|||||||
static StatusBarUserSwitcherContainer getUserSwitcherContainer(KeyguardStatusBarView view) {
|
static StatusBarUserSwitcherContainer getUserSwitcherContainer(KeyguardStatusBarView view) {
|
||||||
return view.findViewById(R.id.user_switcher_container);
|
return view.findViewById(R.id.user_switcher_container);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** */
|
|
||||||
@Binds
|
|
||||||
@KeyguardStatusBarViewScope
|
|
||||||
abstract StatusBarUserSwitcherController bindStatusBarUserSwitcherController(
|
|
||||||
StatusBarUserSwitcherControllerImpl controller);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,8 +32,6 @@ import com.android.systemui.animation.Expandable
|
|||||||
import com.android.systemui.broadcast.BroadcastDispatcher
|
import com.android.systemui.broadcast.BroadcastDispatcher
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
import com.android.systemui.dagger.qualifiers.Background
|
import com.android.systemui.dagger.qualifiers.Background
|
||||||
import com.android.systemui.flags.FeatureFlags
|
|
||||||
import com.android.systemui.flags.Flags
|
|
||||||
import com.android.systemui.globalactions.GlobalActionsDialogLite
|
import com.android.systemui.globalactions.GlobalActionsDialogLite
|
||||||
import com.android.systemui.plugins.ActivityStarter
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
import com.android.systemui.qs.FgsManagerController
|
import com.android.systemui.qs.FgsManagerController
|
||||||
@@ -42,10 +40,9 @@ import com.android.systemui.qs.footer.data.model.UserSwitcherStatusModel
|
|||||||
import com.android.systemui.qs.footer.data.repository.ForegroundServicesRepository
|
import com.android.systemui.qs.footer.data.repository.ForegroundServicesRepository
|
||||||
import com.android.systemui.qs.footer.data.repository.UserSwitcherRepository
|
import com.android.systemui.qs.footer.data.repository.UserSwitcherRepository
|
||||||
import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig
|
import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig
|
||||||
import com.android.systemui.qs.user.UserSwitchDialogController
|
|
||||||
import com.android.systemui.security.data.repository.SecurityRepository
|
import com.android.systemui.security.data.repository.SecurityRepository
|
||||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController
|
import com.android.systemui.statusbar.policy.DeviceProvisionedController
|
||||||
import com.android.systemui.user.UserSwitcherActivity
|
import com.android.systemui.user.domain.interactor.UserInteractor
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
@@ -100,13 +97,12 @@ class FooterActionsInteractorImpl
|
|||||||
@Inject
|
@Inject
|
||||||
constructor(
|
constructor(
|
||||||
private val activityStarter: ActivityStarter,
|
private val activityStarter: ActivityStarter,
|
||||||
private val featureFlags: FeatureFlags,
|
|
||||||
private val metricsLogger: MetricsLogger,
|
private val metricsLogger: MetricsLogger,
|
||||||
private val uiEventLogger: UiEventLogger,
|
private val uiEventLogger: UiEventLogger,
|
||||||
private val deviceProvisionedController: DeviceProvisionedController,
|
private val deviceProvisionedController: DeviceProvisionedController,
|
||||||
private val qsSecurityFooterUtils: QSSecurityFooterUtils,
|
private val qsSecurityFooterUtils: QSSecurityFooterUtils,
|
||||||
private val fgsManagerController: FgsManagerController,
|
private val fgsManagerController: FgsManagerController,
|
||||||
private val userSwitchDialogController: UserSwitchDialogController,
|
private val userInteractor: UserInteractor,
|
||||||
securityRepository: SecurityRepository,
|
securityRepository: SecurityRepository,
|
||||||
foregroundServicesRepository: ForegroundServicesRepository,
|
foregroundServicesRepository: ForegroundServicesRepository,
|
||||||
userSwitcherRepository: UserSwitcherRepository,
|
userSwitcherRepository: UserSwitcherRepository,
|
||||||
@@ -182,22 +178,6 @@ constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun showUserSwitcher(context: Context, expandable: Expandable) {
|
override fun showUserSwitcher(context: Context, expandable: Expandable) {
|
||||||
if (!featureFlags.isEnabled(Flags.FULL_SCREEN_USER_SWITCHER)) {
|
userInteractor.showUserSwitcher(context, expandable)
|
||||||
userSwitchDialogController.showDialog(context, expandable)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val intent =
|
|
||||||
Intent(context, UserSwitcherActivity::class.java).apply {
|
|
||||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
||||||
}
|
|
||||||
|
|
||||||
activityStarter.startActivity(
|
|
||||||
intent,
|
|
||||||
true /* dismissShade */,
|
|
||||||
expandable.activityLaunchController(),
|
|
||||||
true /* showOverlockscreenwhenlocked */,
|
|
||||||
UserHandle.SYSTEM,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ import com.android.systemui.R;
|
|||||||
import com.android.systemui.animation.Interpolators;
|
import com.android.systemui.animation.Interpolators;
|
||||||
import com.android.systemui.battery.BatteryMeterView;
|
import com.android.systemui.battery.BatteryMeterView;
|
||||||
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
|
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
|
||||||
|
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer;
|
||||||
|
import com.android.systemui.user.ui.binder.StatusBarUserChipViewBinder;
|
||||||
|
import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -70,7 +73,7 @@ public class KeyguardStatusBarView extends RelativeLayout {
|
|||||||
private ImageView mMultiUserAvatar;
|
private ImageView mMultiUserAvatar;
|
||||||
private BatteryMeterView mBatteryView;
|
private BatteryMeterView mBatteryView;
|
||||||
private StatusIconContainer mStatusIconContainer;
|
private StatusIconContainer mStatusIconContainer;
|
||||||
private ViewGroup mUserSwitcherContainer;
|
private StatusBarUserSwitcherContainer mUserSwitcherContainer;
|
||||||
|
|
||||||
private boolean mKeyguardUserSwitcherEnabled;
|
private boolean mKeyguardUserSwitcherEnabled;
|
||||||
private boolean mKeyguardUserAvatarEnabled;
|
private boolean mKeyguardUserAvatarEnabled;
|
||||||
@@ -121,8 +124,12 @@ public class KeyguardStatusBarView extends RelativeLayout {
|
|||||||
loadDimens();
|
loadDimens();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ViewGroup getUserSwitcherContainer() {
|
/**
|
||||||
return mUserSwitcherContainer;
|
* Should only be called from {@link KeyguardStatusBarViewController}
|
||||||
|
* @param viewModel view model for the status bar user chip
|
||||||
|
*/
|
||||||
|
void init(StatusBarUserChipViewModel viewModel) {
|
||||||
|
StatusBarUserChipViewBinder.bind(mUserSwitcherContainer, viewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -304,10 +311,7 @@ public class KeyguardStatusBarView extends RelativeLayout {
|
|||||||
lp = (LayoutParams) mStatusIconArea.getLayoutParams();
|
lp = (LayoutParams) mStatusIconArea.getLayoutParams();
|
||||||
lp.removeRule(RelativeLayout.RIGHT_OF);
|
lp.removeRule(RelativeLayout.RIGHT_OF);
|
||||||
lp.width = LayoutParams.WRAP_CONTENT;
|
lp.width = LayoutParams.WRAP_CONTENT;
|
||||||
|
lp.setMarginStart(getResources().getDimensionPixelSize(
|
||||||
LinearLayout.LayoutParams llp =
|
|
||||||
(LinearLayout.LayoutParams) mSystemIconsContainer.getLayoutParams();
|
|
||||||
llp.setMarginStart(getResources().getDimensionPixelSize(
|
|
||||||
R.dimen.system_icons_super_container_margin_start));
|
R.dimen.system_icons_super_container_margin_start));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -339,10 +343,7 @@ public class KeyguardStatusBarView extends RelativeLayout {
|
|||||||
lp = (LayoutParams) mStatusIconArea.getLayoutParams();
|
lp = (LayoutParams) mStatusIconArea.getLayoutParams();
|
||||||
lp.addRule(RelativeLayout.RIGHT_OF, R.id.cutout_space_view);
|
lp.addRule(RelativeLayout.RIGHT_OF, R.id.cutout_space_view);
|
||||||
lp.width = LayoutParams.MATCH_PARENT;
|
lp.width = LayoutParams.MATCH_PARENT;
|
||||||
|
lp.setMarginStart(0);
|
||||||
LinearLayout.LayoutParams llp =
|
|
||||||
(LinearLayout.LayoutParams) mSystemIconsContainer.getLayoutParams();
|
|
||||||
llp.setMarginStart(0);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,13 +59,11 @@ import com.android.systemui.statusbar.notification.stack.AnimationProperties;
|
|||||||
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
|
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
|
||||||
import com.android.systemui.statusbar.phone.fragment.StatusBarIconBlocklistKt;
|
import com.android.systemui.statusbar.phone.fragment.StatusBarIconBlocklistKt;
|
||||||
import com.android.systemui.statusbar.phone.fragment.StatusBarSystemEventAnimator;
|
import com.android.systemui.statusbar.phone.fragment.StatusBarSystemEventAnimator;
|
||||||
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.BatteryController;
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||||
import com.android.systemui.statusbar.policy.UserInfoController;
|
import com.android.systemui.statusbar.policy.UserInfoController;
|
||||||
|
import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel;
|
||||||
import com.android.systemui.util.ViewController;
|
import com.android.systemui.util.ViewController;
|
||||||
import com.android.systemui.util.settings.SecureSettings;
|
import com.android.systemui.util.settings.SecureSettings;
|
||||||
|
|
||||||
@@ -110,9 +108,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
|
|||||||
private final SysuiStatusBarStateController mStatusBarStateController;
|
private final SysuiStatusBarStateController mStatusBarStateController;
|
||||||
private final StatusBarContentInsetsProvider mInsetsProvider;
|
private final StatusBarContentInsetsProvider mInsetsProvider;
|
||||||
private final UserManager mUserManager;
|
private final UserManager mUserManager;
|
||||||
private final StatusBarUserSwitcherFeatureController mFeatureController;
|
private final StatusBarUserChipViewModel mStatusBarUserChipViewModel;
|
||||||
private final StatusBarUserSwitcherController mUserSwitcherController;
|
|
||||||
private final StatusBarUserInfoTracker mStatusBarUserInfoTracker;
|
|
||||||
private final SecureSettings mSecureSettings;
|
private final SecureSettings mSecureSettings;
|
||||||
private final CommandQueue mCommandQueue;
|
private final CommandQueue mCommandQueue;
|
||||||
private final Executor mMainExecutor;
|
private final Executor mMainExecutor;
|
||||||
@@ -276,9 +272,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
|
|||||||
SysuiStatusBarStateController statusBarStateController,
|
SysuiStatusBarStateController statusBarStateController,
|
||||||
StatusBarContentInsetsProvider statusBarContentInsetsProvider,
|
StatusBarContentInsetsProvider statusBarContentInsetsProvider,
|
||||||
UserManager userManager,
|
UserManager userManager,
|
||||||
StatusBarUserSwitcherFeatureController featureController,
|
StatusBarUserChipViewModel userChipViewModel,
|
||||||
StatusBarUserSwitcherController userSwitcherController,
|
|
||||||
StatusBarUserInfoTracker statusBarUserInfoTracker,
|
|
||||||
SecureSettings secureSettings,
|
SecureSettings secureSettings,
|
||||||
CommandQueue commandQueue,
|
CommandQueue commandQueue,
|
||||||
@Main Executor mainExecutor,
|
@Main Executor mainExecutor,
|
||||||
@@ -301,9 +295,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
|
|||||||
mStatusBarStateController = statusBarStateController;
|
mStatusBarStateController = statusBarStateController;
|
||||||
mInsetsProvider = statusBarContentInsetsProvider;
|
mInsetsProvider = statusBarContentInsetsProvider;
|
||||||
mUserManager = userManager;
|
mUserManager = userManager;
|
||||||
mFeatureController = featureController;
|
mStatusBarUserChipViewModel = userChipViewModel;
|
||||||
mUserSwitcherController = userSwitcherController;
|
|
||||||
mStatusBarUserInfoTracker = statusBarUserInfoTracker;
|
|
||||||
mSecureSettings = secureSettings;
|
mSecureSettings = secureSettings;
|
||||||
mCommandQueue = commandQueue;
|
mCommandQueue = commandQueue;
|
||||||
mMainExecutor = mainExecutor;
|
mMainExecutor = mainExecutor;
|
||||||
@@ -328,8 +320,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
|
|||||||
R.dimen.header_notifications_collide_distance);
|
R.dimen.header_notifications_collide_distance);
|
||||||
|
|
||||||
mView.setKeyguardUserAvatarEnabled(
|
mView.setKeyguardUserAvatarEnabled(
|
||||||
!mFeatureController.isStatusBarUserSwitcherFeatureEnabled());
|
!mStatusBarUserChipViewModel.getChipEnabled());
|
||||||
mFeatureController.addCallback(enabled -> mView.setKeyguardUserAvatarEnabled(!enabled));
|
|
||||||
mSystemEventAnimator = new StatusBarSystemEventAnimator(mView, r);
|
mSystemEventAnimator = new StatusBarSystemEventAnimator(mView, r);
|
||||||
|
|
||||||
mDisableStateTracker = new DisableStateTracker(
|
mDisableStateTracker = new DisableStateTracker(
|
||||||
@@ -344,11 +335,11 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
|
|||||||
super.onInit();
|
super.onInit();
|
||||||
mCarrierTextController.init();
|
mCarrierTextController.init();
|
||||||
mBatteryMeterViewController.init();
|
mBatteryMeterViewController.init();
|
||||||
mUserSwitcherController.init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onViewAttached() {
|
protected void onViewAttached() {
|
||||||
|
mView.init(mStatusBarUserChipViewModel);
|
||||||
mConfigurationController.addCallback(mConfigurationListener);
|
mConfigurationController.addCallback(mConfigurationListener);
|
||||||
mAnimationScheduler.addCallback(mAnimationCallback);
|
mAnimationScheduler.addCallback(mAnimationCallback);
|
||||||
mUserInfoController.addCallback(mOnUserInfoChangedListener);
|
mUserInfoController.addCallback(mOnUserInfoChangedListener);
|
||||||
@@ -394,9 +385,6 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
|
|||||||
/** Sets whether user switcher is enabled. */
|
/** Sets whether user switcher is enabled. */
|
||||||
public void setKeyguardUserSwitcherEnabled(boolean enabled) {
|
public void setKeyguardUserSwitcherEnabled(boolean enabled) {
|
||||||
mView.setKeyguardUserSwitcherEnabled(enabled);
|
mView.setKeyguardUserSwitcherEnabled(enabled);
|
||||||
// We don't have a listener for when the user switcher setting changes, so this is
|
|
||||||
// where we re-check the state
|
|
||||||
mStatusBarUserInfoTracker.checkEnabled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets whether this controller should listen to battery updates. */
|
/** Sets whether this controller should listen to battery updates. */
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ import com.android.systemui.Dependency;
|
|||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.plugins.DarkIconDispatcher;
|
import com.android.systemui.plugins.DarkIconDispatcher;
|
||||||
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
|
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
|
||||||
|
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer;
|
||||||
|
import com.android.systemui.user.ui.binder.StatusBarUserChipViewBinder;
|
||||||
|
import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel;
|
||||||
import com.android.systemui.util.leak.RotationUtils;
|
import com.android.systemui.util.leak.RotationUtils;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -73,6 +76,11 @@ public class PhoneStatusBarView extends FrameLayout {
|
|||||||
mTouchEventHandler = handler;
|
mTouchEventHandler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void init(StatusBarUserChipViewModel viewModel) {
|
||||||
|
StatusBarUserSwitcherContainer container = findViewById(R.id.user_switcher_container);
|
||||||
|
StatusBarUserChipViewBinder.bind(container, viewModel);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFinishInflate() {
|
public void onFinishInflate() {
|
||||||
super.onFinishInflate();
|
super.onFinishInflate();
|
||||||
|
|||||||
@@ -23,11 +23,11 @@ import android.view.ViewGroup
|
|||||||
import android.view.ViewTreeObserver
|
import android.view.ViewTreeObserver
|
||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator
|
import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator
|
||||||
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherController
|
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||||
import com.android.systemui.unfold.SysUIUnfoldComponent
|
import com.android.systemui.unfold.SysUIUnfoldComponent
|
||||||
import com.android.systemui.unfold.UNFOLD_STATUS_BAR
|
import com.android.systemui.unfold.UNFOLD_STATUS_BAR
|
||||||
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
|
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
|
||||||
|
import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel
|
||||||
import com.android.systemui.util.ViewController
|
import com.android.systemui.util.ViewController
|
||||||
import com.android.systemui.util.kotlin.getOrNull
|
import com.android.systemui.util.kotlin.getOrNull
|
||||||
import com.android.systemui.util.view.ViewUtil
|
import com.android.systemui.util.view.ViewUtil
|
||||||
@@ -40,7 +40,7 @@ class PhoneStatusBarViewController private constructor(
|
|||||||
view: PhoneStatusBarView,
|
view: PhoneStatusBarView,
|
||||||
@Named(UNFOLD_STATUS_BAR) private val progressProvider: ScopedUnfoldTransitionProgressProvider?,
|
@Named(UNFOLD_STATUS_BAR) private val progressProvider: ScopedUnfoldTransitionProgressProvider?,
|
||||||
private val moveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?,
|
private val moveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?,
|
||||||
private val userSwitcherController: StatusBarUserSwitcherController,
|
private val userChipViewModel: StatusBarUserChipViewModel,
|
||||||
private val viewUtil: ViewUtil,
|
private val viewUtil: ViewUtil,
|
||||||
touchEventHandler: PhoneStatusBarView.TouchEventHandler,
|
touchEventHandler: PhoneStatusBarView.TouchEventHandler,
|
||||||
private val configurationController: ConfigurationController
|
private val configurationController: ConfigurationController
|
||||||
@@ -91,10 +91,10 @@ class PhoneStatusBarViewController private constructor(
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
mView.setTouchEventHandler(touchEventHandler)
|
mView.setTouchEventHandler(touchEventHandler)
|
||||||
|
mView.init(userChipViewModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onInit() {
|
override fun onInit() {
|
||||||
userSwitcherController.init()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setImportantForAccessibility(mode: Int) {
|
fun setImportantForAccessibility(mode: Int) {
|
||||||
@@ -156,9 +156,9 @@ class PhoneStatusBarViewController private constructor(
|
|||||||
private val unfoldComponent: Optional<SysUIUnfoldComponent>,
|
private val unfoldComponent: Optional<SysUIUnfoldComponent>,
|
||||||
@Named(UNFOLD_STATUS_BAR)
|
@Named(UNFOLD_STATUS_BAR)
|
||||||
private val progressProvider: Optional<ScopedUnfoldTransitionProgressProvider>,
|
private val progressProvider: Optional<ScopedUnfoldTransitionProgressProvider>,
|
||||||
private val userSwitcherController: StatusBarUserSwitcherController,
|
private val userChipViewModel: StatusBarUserChipViewModel,
|
||||||
private val viewUtil: ViewUtil,
|
private val viewUtil: ViewUtil,
|
||||||
private val configurationController: ConfigurationController
|
private val configurationController: ConfigurationController,
|
||||||
) {
|
) {
|
||||||
fun create(
|
fun create(
|
||||||
view: PhoneStatusBarView,
|
view: PhoneStatusBarView,
|
||||||
@@ -168,7 +168,7 @@ class PhoneStatusBarViewController private constructor(
|
|||||||
view,
|
view,
|
||||||
progressProvider.getOrNull(),
|
progressProvider.getOrNull(),
|
||||||
unfoldComponent.getOrNull()?.getStatusBarMoveFromCenterAnimationController(),
|
unfoldComponent.getOrNull()?.getStatusBarMoveFromCenterAnimationController(),
|
||||||
userSwitcherController,
|
userChipViewModel,
|
||||||
viewUtil,
|
viewUtil,
|
||||||
touchEventHandler,
|
touchEventHandler,
|
||||||
configurationController
|
configurationController
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ import com.android.systemui.statusbar.phone.PhoneStatusBarViewController;
|
|||||||
import com.android.systemui.statusbar.phone.StatusBarBoundsProvider;
|
import com.android.systemui.statusbar.phone.StatusBarBoundsProvider;
|
||||||
import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
|
import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
|
||||||
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer;
|
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.policy.Clock;
|
||||||
import com.android.systemui.statusbar.window.StatusBarWindowController;
|
import com.android.systemui.statusbar.window.StatusBarWindowController;
|
||||||
|
|
||||||
@@ -39,7 +37,6 @@ import java.util.Set;
|
|||||||
|
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
|
||||||
import dagger.Binds;
|
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
import dagger.multibindings.Multibinds;
|
import dagger.multibindings.Multibinds;
|
||||||
@@ -125,12 +122,6 @@ public interface StatusBarFragmentModule {
|
|||||||
return view.findViewById(R.id.user_switcher_container);
|
return view.findViewById(R.id.user_switcher_container);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** */
|
|
||||||
@Binds
|
|
||||||
@StatusBarFragmentScope
|
|
||||||
StatusBarUserSwitcherController bindStatusBarUserSwitcherController(
|
|
||||||
StatusBarUserSwitcherControllerImpl controller);
|
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
@Provides
|
@Provides
|
||||||
@StatusBarFragmentScope
|
@StatusBarFragmentScope
|
||||||
|
|||||||
@@ -1,134 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.Dumpable
|
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
|
||||||
import com.android.systemui.dagger.qualifiers.Background
|
|
||||||
import com.android.systemui.dagger.qualifiers.Main
|
|
||||||
import com.android.systemui.dump.DumpManager
|
|
||||||
import com.android.systemui.statusbar.policy.CallbackController
|
|
||||||
import com.android.systemui.statusbar.policy.UserInfoController
|
|
||||||
import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener
|
|
||||||
import java.io.PrintWriter
|
|
||||||
import java.util.concurrent.Executor
|
|
||||||
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,
|
|
||||||
private val dumpManager: DumpManager,
|
|
||||||
@Main private val mainExecutor: Executor,
|
|
||||||
@Background private val backgroundExecutor: Executor
|
|
||||||
) : CallbackController<CurrentUserChipInfoUpdatedListener>, Dumpable {
|
|
||||||
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<CurrentUserChipInfoUpdatedListener>()
|
|
||||||
|
|
||||||
private val userInfoChangedListener = OnUserInfoChangedListener { name, picture, _ ->
|
|
||||||
currentUserAvatar = picture
|
|
||||||
currentUserName = name
|
|
||||||
notifyListenersUserInfoChanged()
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
dumpManager.registerDumpable(TAG, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Force a check to [UserManager.isUserSwitcherEnabled], and update listeners if the value has
|
|
||||||
* changed
|
|
||||||
*/
|
|
||||||
fun checkEnabled() {
|
|
||||||
backgroundExecutor.execute {
|
|
||||||
// Check on a background thread to avoid main thread Binder calls
|
|
||||||
val wasEnabled = userSwitcherEnabled
|
|
||||||
userSwitcherEnabled = userManager.isUserSwitcherEnabled
|
|
||||||
|
|
||||||
if (wasEnabled != userSwitcherEnabled) {
|
|
||||||
mainExecutor.execute {
|
|
||||||
notifyListenersSettingChanged()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun dump(pw: PrintWriter, args: Array<out String>) {
|
|
||||||
pw.println(" userSwitcherEnabled=$userSwitcherEnabled")
|
|
||||||
pw.println(" listening=$listening")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CurrentUserChipInfoUpdatedListener {
|
|
||||||
fun onCurrentUserChipInfoUpdated()
|
|
||||||
fun onStatusBarUserSwitcherSettingChanged(enabled: Boolean) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
private const val TAG = "StatusBarUserInfoTracker"
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.Intent
|
|
||||||
import android.os.UserHandle
|
|
||||||
import android.view.View
|
|
||||||
import com.android.systemui.animation.Expandable
|
|
||||||
import com.android.systemui.flags.FeatureFlags
|
|
||||||
import com.android.systemui.flags.Flags
|
|
||||||
import com.android.systemui.plugins.ActivityStarter
|
|
||||||
import com.android.systemui.plugins.FalsingManager
|
|
||||||
|
|
||||||
import com.android.systemui.qs.user.UserSwitchDialogController
|
|
||||||
import com.android.systemui.user.UserSwitcherActivity
|
|
||||||
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,
|
|
||||||
private val featureFlags: FeatureFlags,
|
|
||||||
private val activityStarter: ActivityStarter,
|
|
||||||
private val falsingManager: FalsingManager
|
|
||||||
) : ViewController<StatusBarUserSwitcherContainer>(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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun onViewAttached() {
|
|
||||||
tracker.addCallback(listener)
|
|
||||||
featureController.addCallback(featureFlagListener)
|
|
||||||
mView.setOnClickListener { view: View ->
|
|
||||||
if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
|
|
||||||
return@setOnClickListener
|
|
||||||
}
|
|
||||||
|
|
||||||
if (featureFlags.isEnabled(Flags.FULL_SCREEN_USER_SWITCHER)) {
|
|
||||||
val intent = Intent(context, UserSwitcherActivity::class.java)
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
||||||
|
|
||||||
activityStarter.startActivity(intent, true /* dismissShade */,
|
|
||||||
null /* ActivityLaunchAnimator.Controller */,
|
|
||||||
true /* showOverlockscreenwhenlocked */, UserHandle.SYSTEM)
|
|
||||||
} else {
|
|
||||||
userSwitcherDialogController.showDialog(view.context, Expandable.fromView(view))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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"
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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<OnUserSwitcherPreferenceChangeListener> {
|
|
||||||
private val listeners = mutableListOf<OnUserSwitcherPreferenceChangeListener>()
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
@@ -23,6 +23,7 @@ import android.os.UserHandle
|
|||||||
import android.os.UserManager
|
import android.os.UserManager
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
|
import com.android.systemui.R
|
||||||
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
|
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
|
||||||
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
@@ -79,6 +80,9 @@ interface UserRepository {
|
|||||||
/** Whether we've scheduled the creation of a guest user. */
|
/** Whether we've scheduled the creation of a guest user. */
|
||||||
val isGuestUserCreationScheduled: AtomicBoolean
|
val isGuestUserCreationScheduled: AtomicBoolean
|
||||||
|
|
||||||
|
/** Whether to enable the status bar user chip (which launches the user switcher) */
|
||||||
|
val isStatusBarUserChipEnabled: Boolean
|
||||||
|
|
||||||
/** The user of the secondary service. */
|
/** The user of the secondary service. */
|
||||||
var secondaryUserId: Int
|
var secondaryUserId: Int
|
||||||
|
|
||||||
@@ -127,6 +131,9 @@ constructor(
|
|||||||
|
|
||||||
override val isGuestUserCreationScheduled = AtomicBoolean()
|
override val isGuestUserCreationScheduled = AtomicBoolean()
|
||||||
|
|
||||||
|
override val isStatusBarUserChipEnabled: Boolean =
|
||||||
|
appContext.resources.getBoolean(R.bool.flag_user_switcher_chip)
|
||||||
|
|
||||||
override var secondaryUserId: Int = UserHandle.USER_NULL
|
override var secondaryUserId: Int = UserHandle.USER_NULL
|
||||||
|
|
||||||
override var isRefreshUsersPaused: Boolean = false
|
override var isRefreshUsersPaused: Boolean = false
|
||||||
|
|||||||
@@ -34,15 +34,19 @@ import android.util.Log
|
|||||||
import com.android.internal.util.UserIcons
|
import com.android.internal.util.UserIcons
|
||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
import com.android.systemui.SystemUISecondaryUserService
|
import com.android.systemui.SystemUISecondaryUserService
|
||||||
|
import com.android.systemui.animation.Expandable
|
||||||
import com.android.systemui.broadcast.BroadcastDispatcher
|
import com.android.systemui.broadcast.BroadcastDispatcher
|
||||||
import com.android.systemui.common.shared.model.Text
|
import com.android.systemui.common.shared.model.Text
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
import com.android.systemui.dagger.qualifiers.Application
|
import com.android.systemui.dagger.qualifiers.Application
|
||||||
import com.android.systemui.dagger.qualifiers.Background
|
import com.android.systemui.dagger.qualifiers.Background
|
||||||
|
import com.android.systemui.flags.FeatureFlags
|
||||||
|
import com.android.systemui.flags.Flags
|
||||||
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
|
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
|
||||||
import com.android.systemui.plugins.ActivityStarter
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
import com.android.systemui.qs.user.UserSwitchDialogController
|
import com.android.systemui.qs.user.UserSwitchDialogController
|
||||||
import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
|
import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
|
||||||
|
import com.android.systemui.user.UserSwitcherActivity
|
||||||
import com.android.systemui.user.data.model.UserSwitcherSettingsModel
|
import com.android.systemui.user.data.model.UserSwitcherSettingsModel
|
||||||
import com.android.systemui.user.data.repository.UserRepository
|
import com.android.systemui.user.data.repository.UserRepository
|
||||||
import com.android.systemui.user.data.source.UserRecord
|
import com.android.systemui.user.data.source.UserRecord
|
||||||
@@ -81,6 +85,7 @@ constructor(
|
|||||||
private val repository: UserRepository,
|
private val repository: UserRepository,
|
||||||
private val activityStarter: ActivityStarter,
|
private val activityStarter: ActivityStarter,
|
||||||
private val keyguardInteractor: KeyguardInteractor,
|
private val keyguardInteractor: KeyguardInteractor,
|
||||||
|
private val featureFlags: FeatureFlags,
|
||||||
private val manager: UserManager,
|
private val manager: UserManager,
|
||||||
@Application private val applicationScope: CoroutineScope,
|
@Application private val applicationScope: CoroutineScope,
|
||||||
telephonyInteractor: TelephonyInteractor,
|
telephonyInteractor: TelephonyInteractor,
|
||||||
@@ -256,6 +261,9 @@ constructor(
|
|||||||
/** Whether the guest user is currently being reset. */
|
/** Whether the guest user is currently being reset. */
|
||||||
val isGuestUserResetting: Boolean = guestUserInteractor.isGuestUserResetting
|
val isGuestUserResetting: Boolean = guestUserInteractor.isGuestUserResetting
|
||||||
|
|
||||||
|
/** Whether to enable the user chip in the status bar */
|
||||||
|
val isStatusBarUserChipEnabled: Boolean = repository.isStatusBarUserChipEnabled
|
||||||
|
|
||||||
private val _dialogShowRequests = MutableStateFlow<ShowDialogRequestModel?>(null)
|
private val _dialogShowRequests = MutableStateFlow<ShowDialogRequestModel?>(null)
|
||||||
val dialogShowRequests: Flow<ShowDialogRequestModel?> = _dialogShowRequests.asStateFlow()
|
val dialogShowRequests: Flow<ShowDialogRequestModel?> = _dialogShowRequests.asStateFlow()
|
||||||
|
|
||||||
@@ -468,6 +476,26 @@ constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun showUserSwitcher(context: Context, expandable: Expandable) {
|
||||||
|
if (!featureFlags.isEnabled(Flags.FULL_SCREEN_USER_SWITCHER)) {
|
||||||
|
showDialog(ShowDialogRequestModel.ShowUserSwitcherDialog)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val intent =
|
||||||
|
Intent(context, UserSwitcherActivity::class.java).apply {
|
||||||
|
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
}
|
||||||
|
|
||||||
|
activityStarter.startActivity(
|
||||||
|
intent,
|
||||||
|
true /* dismissShade */,
|
||||||
|
expandable.activityLaunchController(),
|
||||||
|
true /* showOverlockscreenwhenlocked */,
|
||||||
|
UserHandle.SYSTEM,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun showDialog(request: ShowDialogRequestModel) {
|
private fun showDialog(request: ShowDialogRequestModel) {
|
||||||
_dialogShowRequests.value = request
|
_dialogShowRequests.value = request
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,4 +43,7 @@ sealed class ShowDialogRequestModel(
|
|||||||
val onExitGuestUser: (guestId: Int, targetId: Int, forceRemoveGuest: Boolean) -> Unit,
|
val onExitGuestUser: (guestId: Int, targetId: Int, forceRemoveGuest: Boolean) -> Unit,
|
||||||
override val dialogShower: UserSwitchDialogController.DialogShower?,
|
override val dialogShower: UserSwitchDialogController.DialogShower?,
|
||||||
) : ShowDialogRequestModel(dialogShower)
|
) : ShowDialogRequestModel(dialogShower)
|
||||||
|
|
||||||
|
/** Show the user switcher dialog */
|
||||||
|
object ShowUserSwitcherDialog : ShowDialogRequestModel()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* 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.user.ui.binder
|
||||||
|
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
|
import com.android.systemui.animation.Expandable
|
||||||
|
import com.android.systemui.common.ui.binder.TextViewBinder
|
||||||
|
import com.android.systemui.lifecycle.repeatWhenAttached
|
||||||
|
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer
|
||||||
|
import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel
|
||||||
|
import kotlinx.coroutines.InternalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.flow.collect
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
@OptIn(InternalCoroutinesApi::class)
|
||||||
|
object StatusBarUserChipViewBinder {
|
||||||
|
/** Binds the status bar user chip view model to the given view */
|
||||||
|
@JvmStatic
|
||||||
|
fun bind(
|
||||||
|
view: StatusBarUserSwitcherContainer,
|
||||||
|
viewModel: StatusBarUserChipViewModel,
|
||||||
|
) {
|
||||||
|
view.repeatWhenAttached {
|
||||||
|
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
|
launch {
|
||||||
|
viewModel.isChipVisible.collect { isVisible -> view.isVisible = isVisible }
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.userName.collect { name -> TextViewBinder.bind(view.text, name) }
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.userAvatar.collect { avatar -> view.avatar.setImageDrawable(avatar) }
|
||||||
|
}
|
||||||
|
|
||||||
|
bindButton(view, viewModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bindButton(
|
||||||
|
view: StatusBarUserSwitcherContainer,
|
||||||
|
viewModel: StatusBarUserChipViewModel,
|
||||||
|
) {
|
||||||
|
view.setOnClickListener { viewModel.onClick(Expandable.fromView(view)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package com.android.systemui.user.ui.dialog
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.provider.Settings
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import com.android.internal.logging.UiEventLogger
|
||||||
|
import com.android.systemui.R
|
||||||
|
import com.android.systemui.animation.DialogLaunchAnimator
|
||||||
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
|
import com.android.systemui.plugins.FalsingManager
|
||||||
|
import com.android.systemui.qs.QSUserSwitcherEvent
|
||||||
|
import com.android.systemui.qs.tiles.UserDetailView
|
||||||
|
import com.android.systemui.statusbar.phone.SystemUIDialog
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracted from the old UserSwitchDialogController. This is the dialog version of the full-screen
|
||||||
|
* user switcher. See config_enableFullscreenUserSwitcher
|
||||||
|
*/
|
||||||
|
class UserSwitchDialog(
|
||||||
|
context: Context,
|
||||||
|
adapter: UserDetailView.Adapter,
|
||||||
|
uiEventLogger: UiEventLogger,
|
||||||
|
falsingManager: FalsingManager,
|
||||||
|
activityStarter: ActivityStarter,
|
||||||
|
dialogLaunchAnimator: DialogLaunchAnimator,
|
||||||
|
) : SystemUIDialog(context) {
|
||||||
|
init {
|
||||||
|
setShowForAllUsers(true)
|
||||||
|
setCanceledOnTouchOutside(true)
|
||||||
|
setTitle(R.string.qs_user_switch_dialog_title)
|
||||||
|
setPositiveButton(R.string.quick_settings_done) { _, _ ->
|
||||||
|
uiEventLogger.log(QSUserSwitcherEvent.QS_USER_DETAIL_CLOSE)
|
||||||
|
}
|
||||||
|
setNeutralButton(
|
||||||
|
R.string.quick_settings_more_user_settings,
|
||||||
|
{ _, _ ->
|
||||||
|
if (!falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
|
||||||
|
uiEventLogger.log(QSUserSwitcherEvent.QS_USER_MORE_SETTINGS)
|
||||||
|
val controller =
|
||||||
|
dialogLaunchAnimator.createActivityLaunchController(
|
||||||
|
getButton(BUTTON_NEUTRAL)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (controller == null) {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
activityStarter.postStartActivityDismissingKeyguard(
|
||||||
|
USER_SETTINGS_INTENT,
|
||||||
|
0,
|
||||||
|
controller
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
false /* dismissOnClick */
|
||||||
|
)
|
||||||
|
val gridFrame =
|
||||||
|
LayoutInflater.from(this.context).inflate(R.layout.qs_user_dialog_content, null)
|
||||||
|
setView(gridFrame)
|
||||||
|
|
||||||
|
adapter.linkToViewGroup(gridFrame.findViewById(R.id.grid))
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val USER_SETTINGS_INTENT = Intent(Settings.ACTION_USER_SETTINGS)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ package com.android.systemui.user.ui.dialog
|
|||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.android.internal.jank.InteractionJankMonitor
|
import com.android.internal.jank.InteractionJankMonitor
|
||||||
|
import com.android.internal.logging.UiEventLogger
|
||||||
import com.android.settingslib.users.UserCreatingDialog
|
import com.android.settingslib.users.UserCreatingDialog
|
||||||
import com.android.systemui.CoreStartable
|
import com.android.systemui.CoreStartable
|
||||||
import com.android.systemui.animation.DialogCuj
|
import com.android.systemui.animation.DialogCuj
|
||||||
@@ -27,11 +28,14 @@ import com.android.systemui.animation.DialogLaunchAnimator
|
|||||||
import com.android.systemui.broadcast.BroadcastSender
|
import com.android.systemui.broadcast.BroadcastSender
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
import com.android.systemui.dagger.qualifiers.Application
|
import com.android.systemui.dagger.qualifiers.Application
|
||||||
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
import com.android.systemui.plugins.FalsingManager
|
import com.android.systemui.plugins.FalsingManager
|
||||||
|
import com.android.systemui.qs.tiles.UserDetailView
|
||||||
import com.android.systemui.user.domain.interactor.UserInteractor
|
import com.android.systemui.user.domain.interactor.UserInteractor
|
||||||
import com.android.systemui.user.domain.model.ShowDialogRequestModel
|
import com.android.systemui.user.domain.model.ShowDialogRequestModel
|
||||||
import dagger.Lazy
|
import dagger.Lazy
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Provider
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.filterNotNull
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -47,6 +51,9 @@ constructor(
|
|||||||
private val broadcastSender: Lazy<BroadcastSender>,
|
private val broadcastSender: Lazy<BroadcastSender>,
|
||||||
private val dialogLaunchAnimator: Lazy<DialogLaunchAnimator>,
|
private val dialogLaunchAnimator: Lazy<DialogLaunchAnimator>,
|
||||||
private val interactor: Lazy<UserInteractor>,
|
private val interactor: Lazy<UserInteractor>,
|
||||||
|
private val userDetailAdapterProvider: Provider<UserDetailView.Adapter>,
|
||||||
|
private val eventLogger: Lazy<UiEventLogger>,
|
||||||
|
private val activityStarter: Lazy<ActivityStarter>,
|
||||||
) : CoreStartable {
|
) : CoreStartable {
|
||||||
|
|
||||||
private var currentDialog: Dialog? = null
|
private var currentDialog: Dialog? = null
|
||||||
@@ -108,6 +115,21 @@ constructor(
|
|||||||
INTERACTION_JANK_EXIT_GUEST_MODE_TAG,
|
INTERACTION_JANK_EXIT_GUEST_MODE_TAG,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
is ShowDialogRequestModel.ShowUserSwitcherDialog ->
|
||||||
|
Pair(
|
||||||
|
UserSwitchDialog(
|
||||||
|
context = context.get(),
|
||||||
|
adapter = userDetailAdapterProvider.get(),
|
||||||
|
uiEventLogger = eventLogger.get(),
|
||||||
|
falsingManager = falsingManager.get(),
|
||||||
|
activityStarter = activityStarter.get(),
|
||||||
|
dialogLaunchAnimator = dialogLaunchAnimator.get(),
|
||||||
|
),
|
||||||
|
DialogCuj(
|
||||||
|
InteractionJankMonitor.CUJ_USER_DIALOG_OPEN,
|
||||||
|
INTERACTION_JANK_EXIT_GUEST_MODE_TAG,
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
currentDialog = dialog
|
currentDialog = dialog
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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.user.ui.viewmodel
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import com.android.systemui.animation.Expandable
|
||||||
|
import com.android.systemui.common.shared.model.Text
|
||||||
|
import com.android.systemui.dagger.qualifiers.Application
|
||||||
|
import com.android.systemui.user.domain.interactor.UserInteractor
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
import kotlinx.coroutines.flow.mapLatest
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
class StatusBarUserChipViewModel
|
||||||
|
@Inject
|
||||||
|
constructor(
|
||||||
|
@Application private val context: Context,
|
||||||
|
interactor: UserInteractor,
|
||||||
|
) {
|
||||||
|
/** Whether the status bar chip ui should be available */
|
||||||
|
val chipEnabled: Boolean = interactor.isStatusBarUserChipEnabled
|
||||||
|
|
||||||
|
/** Whether or not the chip should be showing, based on the number of users */
|
||||||
|
val isChipVisible: Flow<Boolean> =
|
||||||
|
if (!chipEnabled) {
|
||||||
|
flowOf(false)
|
||||||
|
} else {
|
||||||
|
interactor.users.mapLatest { users -> users.size > 1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The display name of the current user */
|
||||||
|
val userName: Flow<Text> = interactor.selectedUser.mapLatest { userModel -> userModel.name }
|
||||||
|
|
||||||
|
/** Avatar for the current user */
|
||||||
|
val userAvatar: Flow<Drawable> =
|
||||||
|
interactor.selectedUser.mapLatest { userModel -> userModel.image }
|
||||||
|
|
||||||
|
/** Action to execute on click. Should launch the user switcher */
|
||||||
|
val onClick: (Expandable) -> Unit = { interactor.showUserSwitcher(context, it) }
|
||||||
|
}
|
||||||
@@ -16,10 +16,8 @@
|
|||||||
|
|
||||||
package com.android.systemui.qs.footer.domain.interactor
|
package com.android.systemui.qs.footer.domain.interactor
|
||||||
|
|
||||||
import android.content.ComponentName
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.UserHandle
|
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
import android.testing.TestableLooper
|
import android.testing.TestableLooper
|
||||||
@@ -30,17 +28,13 @@ import com.android.internal.logging.testing.UiEventLoggerFake
|
|||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.animation.ActivityLaunchAnimator
|
import com.android.systemui.animation.ActivityLaunchAnimator
|
||||||
import com.android.systemui.animation.Expandable
|
import com.android.systemui.animation.Expandable
|
||||||
import com.android.systemui.flags.FakeFeatureFlags
|
|
||||||
import com.android.systemui.flags.Flags
|
|
||||||
import com.android.systemui.globalactions.GlobalActionsDialogLite
|
import com.android.systemui.globalactions.GlobalActionsDialogLite
|
||||||
import com.android.systemui.plugins.ActivityStarter
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
import com.android.systemui.qs.QSSecurityFooterUtils
|
import com.android.systemui.qs.QSSecurityFooterUtils
|
||||||
import com.android.systemui.qs.footer.FooterActionsTestUtils
|
import com.android.systemui.qs.footer.FooterActionsTestUtils
|
||||||
import com.android.systemui.qs.user.UserSwitchDialogController
|
|
||||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController
|
import com.android.systemui.statusbar.policy.DeviceProvisionedController
|
||||||
import com.android.systemui.truth.correspondence.FakeUiEvent
|
import com.android.systemui.truth.correspondence.FakeUiEvent
|
||||||
import com.android.systemui.truth.correspondence.LogMaker
|
import com.android.systemui.truth.correspondence.LogMaker
|
||||||
import com.android.systemui.user.UserSwitcherActivity
|
|
||||||
import com.android.systemui.util.mockito.any
|
import com.android.systemui.util.mockito.any
|
||||||
import com.android.systemui.util.mockito.argumentCaptor
|
import com.android.systemui.util.mockito.argumentCaptor
|
||||||
import com.android.systemui.util.mockito.eq
|
import com.android.systemui.util.mockito.eq
|
||||||
@@ -156,54 +150,4 @@ class FooterActionsInteractorTest : SysuiTestCase() {
|
|||||||
// We only unlock the device.
|
// We only unlock the device.
|
||||||
verify(activityStarter).postQSRunnableDismissingKeyguard(any())
|
verify(activityStarter).postQSRunnableDismissingKeyguard(any())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun showUserSwitcher_fullScreenDisabled() {
|
|
||||||
val featureFlags = FakeFeatureFlags().apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
|
|
||||||
val userSwitchDialogController = mock<UserSwitchDialogController>()
|
|
||||||
val underTest =
|
|
||||||
utils.footerActionsInteractor(
|
|
||||||
featureFlags = featureFlags,
|
|
||||||
userSwitchDialogController = userSwitchDialogController,
|
|
||||||
)
|
|
||||||
|
|
||||||
val expandable = mock<Expandable>()
|
|
||||||
underTest.showUserSwitcher(context, expandable)
|
|
||||||
|
|
||||||
// Dialog is shown.
|
|
||||||
verify(userSwitchDialogController).showDialog(context, expandable)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun showUserSwitcher_fullScreenEnabled() {
|
|
||||||
val featureFlags = FakeFeatureFlags().apply { set(Flags.FULL_SCREEN_USER_SWITCHER, true) }
|
|
||||||
val activityStarter = mock<ActivityStarter>()
|
|
||||||
val underTest =
|
|
||||||
utils.footerActionsInteractor(
|
|
||||||
featureFlags = featureFlags,
|
|
||||||
activityStarter = activityStarter,
|
|
||||||
)
|
|
||||||
|
|
||||||
// The clicked expandable.
|
|
||||||
val expandable = mock<Expandable>()
|
|
||||||
underTest.showUserSwitcher(context, expandable)
|
|
||||||
|
|
||||||
// Dialog is shown.
|
|
||||||
val intentCaptor = argumentCaptor<Intent>()
|
|
||||||
verify(activityStarter)
|
|
||||||
.startActivity(
|
|
||||||
intentCaptor.capture(),
|
|
||||||
/* dismissShade= */ eq(true),
|
|
||||||
/* ActivityLaunchAnimator.Controller= */ nullable(),
|
|
||||||
/* showOverLockscreenWhenLocked= */ eq(true),
|
|
||||||
eq(UserHandle.SYSTEM),
|
|
||||||
)
|
|
||||||
assertThat(intentCaptor.value.component)
|
|
||||||
.isEqualTo(
|
|
||||||
ComponentName(
|
|
||||||
context,
|
|
||||||
UserSwitcherActivity::class.java,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,14 +56,12 @@ import com.android.systemui.shade.NotificationPanelViewController;
|
|||||||
import com.android.systemui.statusbar.CommandQueue;
|
import com.android.systemui.statusbar.CommandQueue;
|
||||||
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||||
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
|
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.BatteryController;
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
|
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||||
import com.android.systemui.statusbar.policy.UserInfoController;
|
import com.android.systemui.statusbar.policy.UserInfoController;
|
||||||
|
import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel;
|
||||||
import com.android.systemui.util.concurrency.FakeExecutor;
|
import com.android.systemui.util.concurrency.FakeExecutor;
|
||||||
import com.android.systemui.util.settings.SecureSettings;
|
import com.android.systemui.util.settings.SecureSettings;
|
||||||
import com.android.systemui.util.time.FakeSystemClock;
|
import com.android.systemui.util.time.FakeSystemClock;
|
||||||
@@ -112,16 +110,12 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
|
|||||||
private StatusBarContentInsetsProvider mStatusBarContentInsetsProvider;
|
private StatusBarContentInsetsProvider mStatusBarContentInsetsProvider;
|
||||||
@Mock
|
@Mock
|
||||||
private UserManager mUserManager;
|
private UserManager mUserManager;
|
||||||
|
@Mock
|
||||||
|
private StatusBarUserChipViewModel mStatusBarUserChipViewModel;
|
||||||
@Captor
|
@Captor
|
||||||
private ArgumentCaptor<ConfigurationListener> mConfigurationListenerCaptor;
|
private ArgumentCaptor<ConfigurationListener> mConfigurationListenerCaptor;
|
||||||
@Captor
|
@Captor
|
||||||
private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardCallbackCaptor;
|
private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardCallbackCaptor;
|
||||||
@Mock
|
|
||||||
private StatusBarUserSwitcherFeatureController mStatusBarUserSwitcherFeatureController;
|
|
||||||
@Mock
|
|
||||||
private StatusBarUserSwitcherController mStatusBarUserSwitcherController;
|
|
||||||
@Mock
|
|
||||||
private StatusBarUserInfoTracker mStatusBarUserInfoTracker;
|
|
||||||
@Mock private SecureSettings mSecureSettings;
|
@Mock private SecureSettings mSecureSettings;
|
||||||
@Mock private CommandQueue mCommandQueue;
|
@Mock private CommandQueue mCommandQueue;
|
||||||
@Mock private KeyguardLogger mLogger;
|
@Mock private KeyguardLogger mLogger;
|
||||||
@@ -169,9 +163,7 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
|
|||||||
mStatusBarStateController,
|
mStatusBarStateController,
|
||||||
mStatusBarContentInsetsProvider,
|
mStatusBarContentInsetsProvider,
|
||||||
mUserManager,
|
mUserManager,
|
||||||
mStatusBarUserSwitcherFeatureController,
|
mStatusBarUserChipViewModel,
|
||||||
mStatusBarUserSwitcherController,
|
|
||||||
mStatusBarUserInfoTracker,
|
|
||||||
mSecureSettings,
|
mSecureSettings,
|
||||||
mCommandQueue,
|
mCommandQueue,
|
||||||
mFakeExecutor,
|
mFakeExecutor,
|
||||||
@@ -479,8 +471,7 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testNewUserSwitcherDisablesAvatar_newUiOn() {
|
public void testNewUserSwitcherDisablesAvatar_newUiOn() {
|
||||||
// GIVEN the status bar user switcher chip is enabled
|
// GIVEN the status bar user switcher chip is enabled
|
||||||
when(mStatusBarUserSwitcherFeatureController.isStatusBarUserSwitcherFeatureEnabled())
|
when(mStatusBarUserChipViewModel.getChipEnabled()).thenReturn(true);
|
||||||
.thenReturn(true);
|
|
||||||
|
|
||||||
// WHEN the controller is created
|
// WHEN the controller is created
|
||||||
mController = createController();
|
mController = createController();
|
||||||
@@ -492,8 +483,7 @@ public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testNewUserSwitcherDisablesAvatar_newUiOff() {
|
public void testNewUserSwitcherDisablesAvatar_newUiOff() {
|
||||||
// GIVEN the status bar user switcher chip is disabled
|
// GIVEN the status bar user switcher chip is disabled
|
||||||
when(mStatusBarUserSwitcherFeatureController.isStatusBarUserSwitcherFeatureEnabled())
|
when(mStatusBarUserChipViewModel.getChipEnabled()).thenReturn(false);
|
||||||
.thenReturn(false);
|
|
||||||
|
|
||||||
// WHEN the controller is created
|
// WHEN the controller is created
|
||||||
mController = createController();
|
mController = createController();
|
||||||
|
|||||||
@@ -27,11 +27,11 @@ import androidx.test.platform.app.InstrumentationRegistry
|
|||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.shade.NotificationPanelViewController
|
import com.android.systemui.shade.NotificationPanelViewController
|
||||||
import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherController
|
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||||
import com.android.systemui.unfold.SysUIUnfoldComponent
|
import com.android.systemui.unfold.SysUIUnfoldComponent
|
||||||
import com.android.systemui.unfold.config.UnfoldTransitionConfig
|
import com.android.systemui.unfold.config.UnfoldTransitionConfig
|
||||||
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
|
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
|
||||||
|
import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel
|
||||||
import com.android.systemui.util.mockito.any
|
import com.android.systemui.util.mockito.any
|
||||||
import com.android.systemui.util.view.ViewUtil
|
import com.android.systemui.util.view.ViewUtil
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
@@ -64,7 +64,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
|
|||||||
@Mock
|
@Mock
|
||||||
private lateinit var configurationController: ConfigurationController
|
private lateinit var configurationController: ConfigurationController
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var userSwitcherController: StatusBarUserSwitcherController
|
private lateinit var userChipViewModel: StatusBarUserChipViewModel
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var viewUtil: ViewUtil
|
private lateinit var viewUtil: ViewUtil
|
||||||
|
|
||||||
@@ -79,15 +79,14 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
|
|||||||
`when`(notificationPanelViewController.view).thenReturn(panelView)
|
`when`(notificationPanelViewController.view).thenReturn(panelView)
|
||||||
`when`(sysuiUnfoldComponent.getStatusBarMoveFromCenterAnimationController())
|
`when`(sysuiUnfoldComponent.getStatusBarMoveFromCenterAnimationController())
|
||||||
.thenReturn(moveFromCenterAnimation)
|
.thenReturn(moveFromCenterAnimation)
|
||||||
// create the view on main thread as it requires main looper
|
// create the view and controller on main thread as it requires main looper
|
||||||
InstrumentationRegistry.getInstrumentation().runOnMainSync {
|
InstrumentationRegistry.getInstrumentation().runOnMainSync {
|
||||||
val parent = FrameLayout(mContext) // add parent to keep layout params
|
val parent = FrameLayout(mContext) // add parent to keep layout params
|
||||||
view = LayoutInflater.from(mContext)
|
view = LayoutInflater.from(mContext)
|
||||||
.inflate(R.layout.status_bar, parent, false) as PhoneStatusBarView
|
.inflate(R.layout.status_bar, parent, false) as PhoneStatusBarView
|
||||||
}
|
|
||||||
|
|
||||||
controller = createAndInitController(view)
|
controller = createAndInitController(view)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun constructor_setsTouchHandlerOnView() {
|
fun constructor_setsTouchHandlerOnView() {
|
||||||
@@ -106,7 +105,10 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
|
|||||||
val view = createViewMock()
|
val view = createViewMock()
|
||||||
val argumentCaptor = ArgumentCaptor.forClass(OnPreDrawListener::class.java)
|
val argumentCaptor = ArgumentCaptor.forClass(OnPreDrawListener::class.java)
|
||||||
unfoldConfig.isEnabled = true
|
unfoldConfig.isEnabled = true
|
||||||
|
// create the controller on main thread as it requires main looper
|
||||||
|
InstrumentationRegistry.getInstrumentation().runOnMainSync {
|
||||||
controller = createAndInitController(view)
|
controller = createAndInitController(view)
|
||||||
|
}
|
||||||
|
|
||||||
verify(view.viewTreeObserver).addOnPreDrawListener(argumentCaptor.capture())
|
verify(view.viewTreeObserver).addOnPreDrawListener(argumentCaptor.capture())
|
||||||
argumentCaptor.value.onPreDraw()
|
argumentCaptor.value.onPreDraw()
|
||||||
@@ -126,7 +128,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() {
|
|||||||
return PhoneStatusBarViewController.Factory(
|
return PhoneStatusBarViewController.Factory(
|
||||||
Optional.of(sysuiUnfoldComponent),
|
Optional.of(sysuiUnfoldComponent),
|
||||||
Optional.of(progressProvider),
|
Optional.of(progressProvider),
|
||||||
userSwitcherController,
|
userChipViewModel,
|
||||||
viewUtil,
|
viewUtil,
|
||||||
configurationController
|
configurationController
|
||||||
).create(view, touchEventHandler).also {
|
).create(view, touchEventHandler).also {
|
||||||
|
|||||||
@@ -1,102 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.Intent
|
|
||||||
import android.os.UserHandle
|
|
||||||
import android.testing.AndroidTestingRunner
|
|
||||||
import android.testing.TestableLooper
|
|
||||||
import androidx.test.filters.SmallTest
|
|
||||||
import com.android.systemui.SysuiTestCase
|
|
||||||
import com.android.systemui.flags.FeatureFlags
|
|
||||||
import com.android.systemui.flags.Flags
|
|
||||||
import com.android.systemui.plugins.ActivityStarter
|
|
||||||
import com.android.systemui.plugins.FalsingManager
|
|
||||||
import com.android.systemui.qs.user.UserSwitchDialogController
|
|
||||||
import com.android.systemui.util.mockito.any
|
|
||||||
import com.android.systemui.util.mockito.eq
|
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.mockito.Mock
|
|
||||||
import org.mockito.Mockito.`when`
|
|
||||||
import org.mockito.Mockito.verify
|
|
||||||
import org.mockito.MockitoAnnotations
|
|
||||||
|
|
||||||
@RunWith(AndroidTestingRunner::class)
|
|
||||||
@TestableLooper.RunWithLooper
|
|
||||||
@SmallTest
|
|
||||||
class StatusBarUserSwitcherControllerOldImplTest : SysuiTestCase() {
|
|
||||||
@Mock
|
|
||||||
private lateinit var tracker: StatusBarUserInfoTracker
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private lateinit var featureController: StatusBarUserSwitcherFeatureController
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private lateinit var userSwitcherDialogController: UserSwitchDialogController
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private lateinit var featureFlags: FeatureFlags
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private lateinit var activityStarter: ActivityStarter
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private lateinit var falsingManager: FalsingManager
|
|
||||||
|
|
||||||
private lateinit var statusBarUserSwitcherContainer: StatusBarUserSwitcherContainer
|
|
||||||
private lateinit var controller: StatusBarUserSwitcherControllerImpl
|
|
||||||
|
|
||||||
@Before
|
|
||||||
fun setup() {
|
|
||||||
MockitoAnnotations.initMocks(this)
|
|
||||||
statusBarUserSwitcherContainer = StatusBarUserSwitcherContainer(mContext, null)
|
|
||||||
statusBarUserSwitcherContainer
|
|
||||||
controller = StatusBarUserSwitcherControllerImpl(
|
|
||||||
statusBarUserSwitcherContainer,
|
|
||||||
tracker,
|
|
||||||
featureController,
|
|
||||||
userSwitcherDialogController,
|
|
||||||
featureFlags,
|
|
||||||
activityStarter,
|
|
||||||
falsingManager
|
|
||||||
)
|
|
||||||
controller.init()
|
|
||||||
controller.onViewAttached()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testFalsingManager() {
|
|
||||||
statusBarUserSwitcherContainer.callOnClick()
|
|
||||||
verify(falsingManager).isFalseTap(FalsingManager.LOW_PENALTY)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testStartActivity() {
|
|
||||||
`when`(featureFlags.isEnabled(Flags.FULL_SCREEN_USER_SWITCHER)).thenReturn(false)
|
|
||||||
statusBarUserSwitcherContainer.callOnClick()
|
|
||||||
verify(userSwitcherDialogController).showDialog(any(), any())
|
|
||||||
`when`(featureFlags.isEnabled(Flags.FULL_SCREEN_USER_SWITCHER)).thenReturn(true)
|
|
||||||
statusBarUserSwitcherContainer.callOnClick()
|
|
||||||
verify(activityStarter).startActivity(any(Intent::class.java),
|
|
||||||
eq(true) /* dismissShade */,
|
|
||||||
eq(null) /* animationController */,
|
|
||||||
eq(true) /* showOverLockscreenWhenLocked */,
|
|
||||||
eq(UserHandle.SYSTEM))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -19,6 +19,7 @@ package com.android.systemui.user.domain.interactor
|
|||||||
|
|
||||||
import android.app.ActivityManager
|
import android.app.ActivityManager
|
||||||
import android.app.admin.DevicePolicyManager
|
import android.app.admin.DevicePolicyManager
|
||||||
|
import android.content.ComponentName
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.UserInfo
|
import android.content.pm.UserInfo
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
@@ -33,7 +34,10 @@ import com.android.systemui.GuestResetOrExitSessionReceiver
|
|||||||
import com.android.systemui.GuestResumeSessionReceiver
|
import com.android.systemui.GuestResumeSessionReceiver
|
||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.animation.Expandable
|
||||||
import com.android.systemui.common.shared.model.Text
|
import com.android.systemui.common.shared.model.Text
|
||||||
|
import com.android.systemui.flags.FakeFeatureFlags
|
||||||
|
import com.android.systemui.flags.Flags
|
||||||
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
|
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
|
||||||
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
|
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
|
||||||
import com.android.systemui.plugins.ActivityStarter
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
@@ -41,6 +45,7 @@ import com.android.systemui.qs.user.UserSwitchDialogController
|
|||||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController
|
import com.android.systemui.statusbar.policy.DeviceProvisionedController
|
||||||
import com.android.systemui.telephony.data.repository.FakeTelephonyRepository
|
import com.android.systemui.telephony.data.repository.FakeTelephonyRepository
|
||||||
import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
|
import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
|
||||||
|
import com.android.systemui.user.UserSwitcherActivity
|
||||||
import com.android.systemui.user.data.model.UserSwitcherSettingsModel
|
import com.android.systemui.user.data.model.UserSwitcherSettingsModel
|
||||||
import com.android.systemui.user.data.repository.FakeUserRepository
|
import com.android.systemui.user.data.repository.FakeUserRepository
|
||||||
import com.android.systemui.user.data.source.UserRecord
|
import com.android.systemui.user.data.source.UserRecord
|
||||||
@@ -48,9 +53,11 @@ import com.android.systemui.user.domain.model.ShowDialogRequestModel
|
|||||||
import com.android.systemui.user.shared.model.UserActionModel
|
import com.android.systemui.user.shared.model.UserActionModel
|
||||||
import com.android.systemui.user.shared.model.UserModel
|
import com.android.systemui.user.shared.model.UserModel
|
||||||
import com.android.systemui.util.mockito.any
|
import com.android.systemui.util.mockito.any
|
||||||
|
import com.android.systemui.util.mockito.argumentCaptor
|
||||||
import com.android.systemui.util.mockito.eq
|
import com.android.systemui.util.mockito.eq
|
||||||
import com.android.systemui.util.mockito.kotlinArgumentCaptor
|
import com.android.systemui.util.mockito.kotlinArgumentCaptor
|
||||||
import com.android.systemui.util.mockito.mock
|
import com.android.systemui.util.mockito.mock
|
||||||
|
import com.android.systemui.util.mockito.nullable
|
||||||
import com.android.systemui.util.mockito.whenever
|
import com.android.systemui.util.mockito.whenever
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -90,6 +97,7 @@ class UserInteractorTest : SysuiTestCase() {
|
|||||||
private lateinit var userRepository: FakeUserRepository
|
private lateinit var userRepository: FakeUserRepository
|
||||||
private lateinit var keyguardRepository: FakeKeyguardRepository
|
private lateinit var keyguardRepository: FakeKeyguardRepository
|
||||||
private lateinit var telephonyRepository: FakeTelephonyRepository
|
private lateinit var telephonyRepository: FakeTelephonyRepository
|
||||||
|
private lateinit var featureFlags: FakeFeatureFlags
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
@@ -104,6 +112,7 @@ class UserInteractorTest : SysuiTestCase() {
|
|||||||
SUPERVISED_USER_CREATION_APP_PACKAGE,
|
SUPERVISED_USER_CREATION_APP_PACKAGE,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
featureFlags = FakeFeatureFlags()
|
||||||
userRepository = FakeUserRepository()
|
userRepository = FakeUserRepository()
|
||||||
keyguardRepository = FakeKeyguardRepository()
|
keyguardRepository = FakeKeyguardRepository()
|
||||||
telephonyRepository = FakeTelephonyRepository()
|
telephonyRepository = FakeTelephonyRepository()
|
||||||
@@ -147,7 +156,8 @@ class UserInteractorTest : SysuiTestCase() {
|
|||||||
uiEventLogger = uiEventLogger,
|
uiEventLogger = uiEventLogger,
|
||||||
resumeSessionReceiver = resumeSessionReceiver,
|
resumeSessionReceiver = resumeSessionReceiver,
|
||||||
resetOrExitSessionReceiver = resetOrExitSessionReceiver,
|
resetOrExitSessionReceiver = resetOrExitSessionReceiver,
|
||||||
)
|
),
|
||||||
|
featureFlags = featureFlags,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -715,6 +725,52 @@ class UserInteractorTest : SysuiTestCase() {
|
|||||||
job.cancel()
|
job.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `show user switcher - full screen disabled - shows dialog switcher`() =
|
||||||
|
runBlocking(IMMEDIATE) {
|
||||||
|
featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, false)
|
||||||
|
|
||||||
|
var dialogRequest: ShowDialogRequestModel? = null
|
||||||
|
val expandable = mock<Expandable>()
|
||||||
|
underTest.showUserSwitcher(context, expandable)
|
||||||
|
|
||||||
|
val job = underTest.dialogShowRequests.onEach { dialogRequest = it }.launchIn(this)
|
||||||
|
|
||||||
|
// Dialog is shown.
|
||||||
|
assertThat(dialogRequest).isEqualTo(ShowDialogRequestModel.ShowUserSwitcherDialog)
|
||||||
|
|
||||||
|
underTest.onDialogShown()
|
||||||
|
assertThat(dialogRequest).isNull()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `show user switcher - full screen enabled - launches activity`() {
|
||||||
|
featureFlags.set(Flags.FULL_SCREEN_USER_SWITCHER, true)
|
||||||
|
|
||||||
|
val expandable = mock<Expandable>()
|
||||||
|
underTest.showUserSwitcher(context, expandable)
|
||||||
|
|
||||||
|
// Dialog is shown.
|
||||||
|
val intentCaptor = argumentCaptor<Intent>()
|
||||||
|
verify(activityStarter)
|
||||||
|
.startActivity(
|
||||||
|
intentCaptor.capture(),
|
||||||
|
/* dismissShade= */ eq(true),
|
||||||
|
/* ActivityLaunchAnimator.Controller= */ nullable(),
|
||||||
|
/* showOverLockscreenWhenLocked= */ eq(true),
|
||||||
|
eq(UserHandle.SYSTEM),
|
||||||
|
)
|
||||||
|
assertThat(intentCaptor.value.component)
|
||||||
|
.isEqualTo(
|
||||||
|
ComponentName(
|
||||||
|
context,
|
||||||
|
UserSwitcherActivity::class.java,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun assertUsers(
|
private fun assertUsers(
|
||||||
models: List<UserModel>?,
|
models: List<UserModel>?,
|
||||||
count: Int,
|
count: Int,
|
||||||
|
|||||||
@@ -0,0 +1,306 @@
|
|||||||
|
/*
|
||||||
|
* 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.user.ui.viewmodel
|
||||||
|
|
||||||
|
import android.app.ActivityManager
|
||||||
|
import android.app.admin.DevicePolicyManager
|
||||||
|
import android.content.pm.UserInfo
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.drawable.BitmapDrawable
|
||||||
|
import android.os.UserManager
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.internal.logging.UiEventLogger
|
||||||
|
import com.android.systemui.GuestResetOrExitSessionReceiver
|
||||||
|
import com.android.systemui.GuestResumeSessionReceiver
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.common.shared.model.Text
|
||||||
|
import com.android.systemui.flags.FakeFeatureFlags
|
||||||
|
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
|
||||||
|
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
|
||||||
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
|
import com.android.systemui.statusbar.policy.DeviceProvisionedController
|
||||||
|
import com.android.systemui.telephony.data.repository.FakeTelephonyRepository
|
||||||
|
import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
|
||||||
|
import com.android.systemui.user.data.model.UserSwitcherSettingsModel
|
||||||
|
import com.android.systemui.user.data.repository.FakeUserRepository
|
||||||
|
import com.android.systemui.user.domain.interactor.GuestUserInteractor
|
||||||
|
import com.android.systemui.user.domain.interactor.RefreshUsersScheduler
|
||||||
|
import com.android.systemui.user.domain.interactor.UserInteractor
|
||||||
|
import com.android.systemui.util.mockito.mock
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.flow.toList
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.test.TestScope
|
||||||
|
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||||
|
import kotlinx.coroutines.test.advanceUntilIdle
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import kotlinx.coroutines.yield
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.junit.runners.JUnit4
|
||||||
|
import org.mockito.ArgumentMatchers.anyInt
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito.doAnswer
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(JUnit4::class)
|
||||||
|
class StatusBarUserChipViewModelTest : SysuiTestCase() {
|
||||||
|
@Mock private lateinit var activityStarter: ActivityStarter
|
||||||
|
@Mock private lateinit var activityManager: ActivityManager
|
||||||
|
@Mock private lateinit var manager: UserManager
|
||||||
|
@Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
|
||||||
|
@Mock private lateinit var devicePolicyManager: DevicePolicyManager
|
||||||
|
@Mock private lateinit var uiEventLogger: UiEventLogger
|
||||||
|
@Mock private lateinit var resumeSessionReceiver: GuestResumeSessionReceiver
|
||||||
|
@Mock private lateinit var resetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
|
||||||
|
|
||||||
|
private lateinit var underTest: StatusBarUserChipViewModel
|
||||||
|
|
||||||
|
private val userRepository = FakeUserRepository()
|
||||||
|
private val keyguardRepository = FakeKeyguardRepository()
|
||||||
|
private val featureFlags = FakeFeatureFlags()
|
||||||
|
private lateinit var guestUserInteractor: GuestUserInteractor
|
||||||
|
private lateinit var refreshUsersScheduler: RefreshUsersScheduler
|
||||||
|
|
||||||
|
private val testDispatcher = UnconfinedTestDispatcher()
|
||||||
|
private val testScope = TestScope(testDispatcher)
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
|
||||||
|
doAnswer { invocation ->
|
||||||
|
val userId = invocation.arguments[0] as Int
|
||||||
|
when (userId) {
|
||||||
|
USER_ID_0 -> return@doAnswer USER_IMAGE_0
|
||||||
|
USER_ID_1 -> return@doAnswer USER_IMAGE_1
|
||||||
|
USER_ID_2 -> return@doAnswer USER_IMAGE_2
|
||||||
|
else -> return@doAnswer mock<Bitmap>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.`when`(manager)
|
||||||
|
.getUserIcon(anyInt())
|
||||||
|
|
||||||
|
userRepository.isStatusBarUserChipEnabled = true
|
||||||
|
|
||||||
|
refreshUsersScheduler =
|
||||||
|
RefreshUsersScheduler(
|
||||||
|
applicationScope = testScope.backgroundScope,
|
||||||
|
mainDispatcher = testDispatcher,
|
||||||
|
repository = userRepository,
|
||||||
|
)
|
||||||
|
guestUserInteractor =
|
||||||
|
GuestUserInteractor(
|
||||||
|
applicationContext = context,
|
||||||
|
applicationScope = testScope.backgroundScope,
|
||||||
|
mainDispatcher = testDispatcher,
|
||||||
|
backgroundDispatcher = testDispatcher,
|
||||||
|
manager = manager,
|
||||||
|
repository = userRepository,
|
||||||
|
deviceProvisionedController = deviceProvisionedController,
|
||||||
|
devicePolicyManager = devicePolicyManager,
|
||||||
|
refreshUsersScheduler = refreshUsersScheduler,
|
||||||
|
uiEventLogger = uiEventLogger,
|
||||||
|
resumeSessionReceiver = resumeSessionReceiver,
|
||||||
|
resetOrExitSessionReceiver = resetOrExitSessionReceiver,
|
||||||
|
)
|
||||||
|
|
||||||
|
underTest = viewModel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `config is false - chip is disabled`() {
|
||||||
|
// the enabled bit is set at SystemUI startup, so recreate the view model here
|
||||||
|
userRepository.isStatusBarUserChipEnabled = false
|
||||||
|
underTest = viewModel()
|
||||||
|
|
||||||
|
assertThat(underTest.chipEnabled).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `config is true - chip is enabled`() {
|
||||||
|
// the enabled bit is set at SystemUI startup, so recreate the view model here
|
||||||
|
userRepository.isStatusBarUserChipEnabled = true
|
||||||
|
underTest = viewModel()
|
||||||
|
|
||||||
|
assertThat(underTest.chipEnabled).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `should show chip criteria - single user`() =
|
||||||
|
testScope.runTest {
|
||||||
|
userRepository.setUserInfos(listOf(USER_0))
|
||||||
|
userRepository.setSelectedUserInfo(USER_0)
|
||||||
|
userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
|
||||||
|
|
||||||
|
val values = mutableListOf<Boolean>()
|
||||||
|
|
||||||
|
val job = launch { underTest.isChipVisible.toList(values) }
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
assertThat(values).containsExactly(false)
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `should show chip criteria - multiple users`() =
|
||||||
|
testScope.runTest {
|
||||||
|
setMultipleUsers()
|
||||||
|
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest.isChipVisible.onEach { latest = it }.launchIn(this)
|
||||||
|
yield()
|
||||||
|
|
||||||
|
assertThat(latest).isTrue()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `user chip name - shows selected user info`() =
|
||||||
|
testScope.runTest {
|
||||||
|
setMultipleUsers()
|
||||||
|
|
||||||
|
var latest: Text? = null
|
||||||
|
val job = underTest.userName.onEach { latest = it }.launchIn(this)
|
||||||
|
|
||||||
|
userRepository.setSelectedUserInfo(USER_0)
|
||||||
|
assertThat(latest).isEqualTo(USER_NAME_0)
|
||||||
|
|
||||||
|
userRepository.setSelectedUserInfo(USER_1)
|
||||||
|
assertThat(latest).isEqualTo(USER_NAME_1)
|
||||||
|
|
||||||
|
userRepository.setSelectedUserInfo(USER_2)
|
||||||
|
assertThat(latest).isEqualTo(USER_NAME_2)
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `user chip avatar - shows selected user info`() =
|
||||||
|
testScope.runTest {
|
||||||
|
setMultipleUsers()
|
||||||
|
|
||||||
|
// A little hacky. System server passes us bitmaps and we wrap them in the interactor.
|
||||||
|
// Unwrap them to make sure we're always tracking the current user's bitmap
|
||||||
|
var latest: Bitmap? = null
|
||||||
|
val job =
|
||||||
|
underTest.userAvatar
|
||||||
|
.onEach {
|
||||||
|
if (it !is BitmapDrawable) {
|
||||||
|
latest = null
|
||||||
|
}
|
||||||
|
|
||||||
|
latest = (it as BitmapDrawable).bitmap
|
||||||
|
}
|
||||||
|
.launchIn(this)
|
||||||
|
|
||||||
|
userRepository.setSelectedUserInfo(USER_0)
|
||||||
|
assertThat(latest).isEqualTo(USER_IMAGE_0)
|
||||||
|
|
||||||
|
userRepository.setSelectedUserInfo(USER_1)
|
||||||
|
assertThat(latest).isEqualTo(USER_IMAGE_1)
|
||||||
|
|
||||||
|
userRepository.setSelectedUserInfo(USER_2)
|
||||||
|
assertThat(latest).isEqualTo(USER_IMAGE_2)
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun viewModel(): StatusBarUserChipViewModel {
|
||||||
|
return StatusBarUserChipViewModel(
|
||||||
|
context = context,
|
||||||
|
interactor =
|
||||||
|
UserInteractor(
|
||||||
|
applicationContext = context,
|
||||||
|
repository = userRepository,
|
||||||
|
activityStarter = activityStarter,
|
||||||
|
keyguardInteractor =
|
||||||
|
KeyguardInteractor(
|
||||||
|
repository = keyguardRepository,
|
||||||
|
),
|
||||||
|
featureFlags = featureFlags,
|
||||||
|
manager = manager,
|
||||||
|
applicationScope = testScope.backgroundScope,
|
||||||
|
telephonyInteractor =
|
||||||
|
TelephonyInteractor(
|
||||||
|
repository = FakeTelephonyRepository(),
|
||||||
|
),
|
||||||
|
broadcastDispatcher = fakeBroadcastDispatcher,
|
||||||
|
backgroundDispatcher = testDispatcher,
|
||||||
|
activityManager = activityManager,
|
||||||
|
refreshUsersScheduler = refreshUsersScheduler,
|
||||||
|
guestUserInteractor = guestUserInteractor,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun setMultipleUsers() {
|
||||||
|
userRepository.setUserInfos(listOf(USER_0, USER_1, USER_2))
|
||||||
|
userRepository.setSelectedUserInfo(USER_0)
|
||||||
|
userRepository.setSettings(UserSwitcherSettingsModel(isUserSwitcherEnabled = true))
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val USER_ID_0 = 0
|
||||||
|
private val USER_IMAGE_0 = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
|
||||||
|
private val USER_NAME_0 = Text.Loaded("zero")
|
||||||
|
|
||||||
|
private const val USER_ID_1 = 1
|
||||||
|
private val USER_IMAGE_1 = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
|
||||||
|
private val USER_NAME_1 = Text.Loaded("one")
|
||||||
|
|
||||||
|
private const val USER_ID_2 = 2
|
||||||
|
private val USER_IMAGE_2 = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
|
||||||
|
private val USER_NAME_2 = Text.Loaded("two")
|
||||||
|
|
||||||
|
private val USER_0 =
|
||||||
|
UserInfo(
|
||||||
|
USER_ID_0,
|
||||||
|
USER_NAME_0.text!!,
|
||||||
|
/* iconPath */ "",
|
||||||
|
/* flags */ 0,
|
||||||
|
/* userType */ UserManager.USER_TYPE_FULL_SYSTEM
|
||||||
|
)
|
||||||
|
|
||||||
|
private val USER_1 =
|
||||||
|
UserInfo(
|
||||||
|
USER_ID_1,
|
||||||
|
USER_NAME_1.text!!,
|
||||||
|
/* iconPath */ "",
|
||||||
|
/* flags */ 0,
|
||||||
|
/* userType */ UserManager.USER_TYPE_FULL_SYSTEM
|
||||||
|
)
|
||||||
|
|
||||||
|
private val USER_2 =
|
||||||
|
UserInfo(
|
||||||
|
USER_ID_2,
|
||||||
|
USER_NAME_2.text!!,
|
||||||
|
/* iconPath */ "",
|
||||||
|
/* flags */ 0,
|
||||||
|
/* userType */ UserManager.USER_TYPE_FULL_SYSTEM
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,6 +27,7 @@ import com.android.systemui.GuestResetOrExitSessionReceiver
|
|||||||
import com.android.systemui.GuestResumeSessionReceiver
|
import com.android.systemui.GuestResumeSessionReceiver
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.common.shared.model.Text
|
import com.android.systemui.common.shared.model.Text
|
||||||
|
import com.android.systemui.flags.FakeFeatureFlags
|
||||||
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
|
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
|
||||||
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
|
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
|
||||||
import com.android.systemui.plugins.ActivityStarter
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
@@ -147,6 +148,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
|
|||||||
KeyguardInteractor(
|
KeyguardInteractor(
|
||||||
repository = keyguardRepository,
|
repository = keyguardRepository,
|
||||||
),
|
),
|
||||||
|
featureFlags = FakeFeatureFlags(),
|
||||||
manager = manager,
|
manager = manager,
|
||||||
applicationScope = injectedScope,
|
applicationScope = injectedScope,
|
||||||
telephonyInteractor =
|
telephonyInteractor =
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ import com.android.internal.logging.testing.UiEventLoggerFake
|
|||||||
import com.android.systemui.broadcast.BroadcastDispatcher
|
import com.android.systemui.broadcast.BroadcastDispatcher
|
||||||
import com.android.systemui.classifier.FalsingManagerFake
|
import com.android.systemui.classifier.FalsingManagerFake
|
||||||
import com.android.systemui.dagger.qualifiers.Application
|
import com.android.systemui.dagger.qualifiers.Application
|
||||||
import com.android.systemui.flags.FakeFeatureFlags
|
|
||||||
import com.android.systemui.flags.FeatureFlags
|
|
||||||
import com.android.systemui.globalactions.GlobalActionsDialogLite
|
import com.android.systemui.globalactions.GlobalActionsDialogLite
|
||||||
import com.android.systemui.plugins.ActivityStarter
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
import com.android.systemui.plugins.FalsingManager
|
import com.android.systemui.plugins.FalsingManager
|
||||||
@@ -43,7 +41,6 @@ import com.android.systemui.qs.footer.data.repository.UserSwitcherRepositoryImpl
|
|||||||
import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractor
|
import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractor
|
||||||
import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractorImpl
|
import com.android.systemui.qs.footer.domain.interactor.FooterActionsInteractorImpl
|
||||||
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
|
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
|
||||||
import com.android.systemui.qs.user.UserSwitchDialogController
|
|
||||||
import com.android.systemui.security.data.repository.SecurityRepository
|
import com.android.systemui.security.data.repository.SecurityRepository
|
||||||
import com.android.systemui.security.data.repository.SecurityRepositoryImpl
|
import com.android.systemui.security.data.repository.SecurityRepositoryImpl
|
||||||
import com.android.systemui.settings.FakeUserTracker
|
import com.android.systemui.settings.FakeUserTracker
|
||||||
@@ -54,6 +51,7 @@ import com.android.systemui.statusbar.policy.FakeUserInfoController
|
|||||||
import com.android.systemui.statusbar.policy.SecurityController
|
import com.android.systemui.statusbar.policy.SecurityController
|
||||||
import com.android.systemui.statusbar.policy.UserInfoController
|
import com.android.systemui.statusbar.policy.UserInfoController
|
||||||
import com.android.systemui.statusbar.policy.UserSwitcherController
|
import com.android.systemui.statusbar.policy.UserSwitcherController
|
||||||
|
import com.android.systemui.user.domain.interactor.UserInteractor
|
||||||
import com.android.systemui.util.mockito.mock
|
import com.android.systemui.util.mockito.mock
|
||||||
import com.android.systemui.util.settings.FakeSettings
|
import com.android.systemui.util.settings.FakeSettings
|
||||||
import com.android.systemui.util.settings.GlobalSettings
|
import com.android.systemui.util.settings.GlobalSettings
|
||||||
@@ -97,13 +95,12 @@ class FooterActionsTestUtils(
|
|||||||
/** Create a [FooterActionsInteractor] to be used in tests. */
|
/** Create a [FooterActionsInteractor] to be used in tests. */
|
||||||
fun footerActionsInteractor(
|
fun footerActionsInteractor(
|
||||||
activityStarter: ActivityStarter = mock(),
|
activityStarter: ActivityStarter = mock(),
|
||||||
featureFlags: FeatureFlags = FakeFeatureFlags(),
|
|
||||||
metricsLogger: MetricsLogger = FakeMetricsLogger(),
|
metricsLogger: MetricsLogger = FakeMetricsLogger(),
|
||||||
uiEventLogger: UiEventLogger = UiEventLoggerFake(),
|
uiEventLogger: UiEventLogger = UiEventLoggerFake(),
|
||||||
deviceProvisionedController: DeviceProvisionedController = mock(),
|
deviceProvisionedController: DeviceProvisionedController = mock(),
|
||||||
qsSecurityFooterUtils: QSSecurityFooterUtils = mock(),
|
qsSecurityFooterUtils: QSSecurityFooterUtils = mock(),
|
||||||
fgsManagerController: FgsManagerController = mock(),
|
fgsManagerController: FgsManagerController = mock(),
|
||||||
userSwitchDialogController: UserSwitchDialogController = mock(),
|
userInteractor: UserInteractor = mock(),
|
||||||
securityRepository: SecurityRepository = securityRepository(),
|
securityRepository: SecurityRepository = securityRepository(),
|
||||||
foregroundServicesRepository: ForegroundServicesRepository = foregroundServicesRepository(),
|
foregroundServicesRepository: ForegroundServicesRepository = foregroundServicesRepository(),
|
||||||
userSwitcherRepository: UserSwitcherRepository = userSwitcherRepository(),
|
userSwitcherRepository: UserSwitcherRepository = userSwitcherRepository(),
|
||||||
@@ -112,13 +109,12 @@ class FooterActionsTestUtils(
|
|||||||
): FooterActionsInteractor {
|
): FooterActionsInteractor {
|
||||||
return FooterActionsInteractorImpl(
|
return FooterActionsInteractorImpl(
|
||||||
activityStarter,
|
activityStarter,
|
||||||
featureFlags,
|
|
||||||
metricsLogger,
|
metricsLogger,
|
||||||
uiEventLogger,
|
uiEventLogger,
|
||||||
deviceProvisionedController,
|
deviceProvisionedController,
|
||||||
qsSecurityFooterUtils,
|
qsSecurityFooterUtils,
|
||||||
fgsManagerController,
|
fgsManagerController,
|
||||||
userSwitchDialogController,
|
userInteractor,
|
||||||
securityRepository,
|
securityRepository,
|
||||||
foregroundServicesRepository,
|
foregroundServicesRepository,
|
||||||
userSwitcherRepository,
|
userSwitcherRepository,
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ class FakeUserRepository : UserRepository {
|
|||||||
|
|
||||||
override val isGuestUserCreationScheduled = AtomicBoolean()
|
override val isGuestUserCreationScheduled = AtomicBoolean()
|
||||||
|
|
||||||
|
override var isStatusBarUserChipEnabled: Boolean = false
|
||||||
|
|
||||||
override var secondaryUserId: Int = UserHandle.USER_NULL
|
override var secondaryUserId: Int = UserHandle.USER_NULL
|
||||||
|
|
||||||
override var isRefreshUsersPaused: Boolean = false
|
override var isRefreshUsersPaused: Boolean = false
|
||||||
|
|||||||
Reference in New Issue
Block a user