Merge changes Ia5df853c,Idf15ff5d,I383f1bb9,I0d6a8e4f into tm-qpr-dev

* changes:
  Switching UserSwitcherController implementation.
  Feature flag for UserSwitcherController refactor.
  Extracts interface from UserSwitcherController.
  Cleans up UserSwitcherController API.
This commit is contained in:
Ale Nijamkin
2022-09-24 22:54:32 +00:00
committed by Android (Google) Code Review
21 changed files with 1028 additions and 473 deletions

View File

@@ -813,7 +813,7 @@
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLoggerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManagerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherControllerOldImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLoggerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt
@@ -828,7 +828,7 @@
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SafetyControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerOldImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/VariableDateViewControllerTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/WalletControllerImplTest.kt
-packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt

View File

@@ -22,8 +22,6 @@ import static android.view.WindowInsets.Type.systemBars;
import static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP;
import static com.android.systemui.plugins.FalsingManager.LOW_PENALTY;
import static com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_DISABLED_ALPHA;
import static com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_ENABLED_ALPHA;
import static java.lang.Integer.max;
@@ -87,8 +85,8 @@ import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.policy.BaseUserSwitcherAdapter;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.UserSwitcherController.BaseUserAdapter;
import com.android.systemui.user.data.source.UserRecord;
import com.android.systemui.util.settings.GlobalSettings;
@@ -1137,7 +1135,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
KeyguardUserSwitcherAnchor anchor = mView.findViewById(R.id.user_switcher_anchor);
BaseUserAdapter adapter = new BaseUserAdapter(mUserSwitcherController) {
BaseUserSwitcherAdapter adapter = new BaseUserSwitcherAdapter(mUserSwitcherController) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
UserRecord item = getItem(position);
@@ -1172,8 +1170,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
}
textView.setSelected(item == currentUser);
view.setEnabled(item.isSwitchToEnabled);
view.setAlpha(view.isEnabled() ? USER_SWITCH_ENABLED_ALPHA :
USER_SWITCH_DISABLED_ALPHA);
UserSwitcherController.setSelectableAlpha(view);
return view;
}

View File

@@ -104,6 +104,10 @@ public class Flags {
public static final UnreleasedFlag MODERN_USER_SWITCHER_ACTIVITY =
new UnreleasedFlag(209, true);
/** Whether the new implementation of UserSwitcherController should be used. */
public static final UnreleasedFlag REFACTORED_USER_SWITCHER_CONTROLLER =
new UnreleasedFlag(210, false);
/***************************************/
// 300 - power menu
public static final ReleasedFlag POWER_MENU_LITE =

View File

@@ -16,9 +16,6 @@
package com.android.systemui.qs.tiles;
import static com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_DISABLED_ALPHA;
import static com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_ENABLED_ALPHA;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
@@ -42,6 +39,7 @@ import com.android.systemui.qs.PseudoGridView;
import com.android.systemui.qs.QSUserSwitcherEvent;
import com.android.systemui.qs.user.UserSwitchDialogController;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.BaseUserSwitcherAdapter;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.user.data.source.UserRecord;
@@ -73,7 +71,8 @@ public class UserDetailView extends PseudoGridView {
mAdapter.refresh();
}
public static class Adapter extends UserSwitcherController.BaseUserAdapter
/** Provides views for user detail items. */
public static class Adapter extends BaseUserSwitcherAdapter
implements OnClickListener {
private final Context mContext;
@@ -137,7 +136,7 @@ public class UserDetailView extends PseudoGridView {
v.setActivated(item.isCurrent);
v.setDisabledByAdmin(mController.isDisabledByAdmin(item));
v.setEnabled(item.isSwitchToEnabled);
v.setAlpha(v.isEnabled() ? USER_SWITCH_ENABLED_ALPHA : USER_SWITCH_DISABLED_ALPHA);
UserSwitcherController.setSelectableAlpha(v);
if (item.isCurrent) {
mCurrentUserView = v;

View File

@@ -1,62 +0,0 @@
/*
* Copyright (C) 2016 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;
import android.content.Context;
import android.content.DialogInterface;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.UserSwitcherController;
public class UserUtil {
public static void deleteUserWithPrompt(Context context, int userId,
UserSwitcherController userSwitcherController) {
new RemoveUserDialog(context, userId, userSwitcherController).show();
}
private final static class RemoveUserDialog extends SystemUIDialog implements
DialogInterface.OnClickListener {
private final int mUserId;
private final UserSwitcherController mUserSwitcherController;
public RemoveUserDialog(Context context, int userId,
UserSwitcherController userSwitcherController) {
super(context);
setTitle(R.string.user_remove_user_title);
setMessage(context.getString(R.string.user_remove_user_message));
setButton(DialogInterface.BUTTON_NEUTRAL,
context.getString(android.R.string.cancel), this);
setButton(DialogInterface.BUTTON_POSITIVE,
context.getString(R.string.user_remove_user_remove), this);
setCanceledOnTouchOutside(false);
mUserId = userId;
mUserSwitcherController = userSwitcherController;
}
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == BUTTON_NEUTRAL) {
cancel();
} else {
dismiss();
mUserSwitcherController.removeUserId(mUserId);
}
}
}
}

View File

@@ -33,6 +33,7 @@ import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.qs.FooterActionsView;
import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.qs.user.UserSwitchDialogController;
import com.android.systemui.statusbar.policy.BaseUserSwitcherAdapter;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.user.UserSwitcherActivity;
import com.android.systemui.util.ViewController;
@@ -49,7 +50,7 @@ public class MultiUserSwitchController extends ViewController<MultiUserSwitch> {
private final ActivityStarter mActivityStarter;
private final FeatureFlags mFeatureFlags;
private UserSwitcherController.BaseUserAdapter mUserListener;
private BaseUserSwitcherAdapter mUserListener;
private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
@Override
@@ -135,7 +136,7 @@ public class MultiUserSwitchController extends ViewController<MultiUserSwitch> {
final UserSwitcherController controller = mUserSwitcherController;
if (controller != null) {
mUserListener = new UserSwitcherController.BaseUserAdapter(controller) {
mUserListener = new BaseUserSwitcherAdapter(controller) {
@Override
public void notifyDataSetChanged() {
mView.refreshContentDescription(getCurrentUser());

View File

@@ -0,0 +1,119 @@
/*
* 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.policy
import android.content.Context
import android.graphics.ColorFilter
import android.graphics.ColorMatrix
import android.graphics.ColorMatrixColorFilter
import android.graphics.drawable.Drawable
import android.os.UserHandle
import android.widget.BaseAdapter
import com.android.systemui.qs.user.UserSwitchDialogController.DialogShower
import com.android.systemui.user.data.source.UserRecord
import com.android.systemui.user.legacyhelper.ui.LegacyUserUiHelper.getUserRecordName
import com.android.systemui.user.legacyhelper.ui.LegacyUserUiHelper.getUserSwitcherActionIconResourceId
import java.lang.ref.WeakReference
/** Provides views for user switcher experiences. */
abstract class BaseUserSwitcherAdapter
protected constructor(
protected val controller: UserSwitcherController,
) : BaseAdapter() {
protected open val users: ArrayList<UserRecord>
get() = controller.users
init {
controller.addAdapter(WeakReference(this))
}
override fun getCount(): Int {
return if (controller.isKeyguardShowing) {
users.count { !it.isRestricted }
} else {
users.size
}
}
override fun getItem(position: Int): UserRecord {
return users[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
/**
* Notifies that a user item in the UI has been clicked.
*
* If the user switcher is hosted in a dialog, passing a non-null [dialogShower] will allow
* animation to and from the parent dialog.
*/
@JvmOverloads
fun onUserListItemClicked(
record: UserRecord,
dialogShower: DialogShower? = null,
) {
controller.onUserListItemClicked(record, dialogShower)
}
open fun getName(context: Context, item: UserRecord): String {
return getName(context, item, false)
}
/** Returns the name for the given {@link UserRecord}. */
open fun getName(context: Context, item: UserRecord, isTablet: Boolean): String {
return getUserRecordName(
context = context,
record = item,
isGuestUserAutoCreated = controller.isGuestUserAutoCreated,
isGuestUserResetting = controller.isGuestUserResetting,
isTablet = isTablet,
)
}
fun refresh() {
controller.refreshUsers(UserHandle.USER_NULL)
}
companion object {
@JvmStatic
protected val disabledUserAvatarColorFilter: ColorFilter by lazy {
val matrix = ColorMatrix()
matrix.setSaturation(0f) // 0 - grayscale
ColorMatrixColorFilter(matrix)
}
@JvmStatic
@JvmOverloads
protected fun getIconDrawable(
context: Context,
item: UserRecord,
isTablet: Boolean = false,
): Drawable {
val iconRes =
getUserSwitcherActionIconResourceId(
item.isAddUser,
item.isGuest,
item.isAddSupervisedUser,
isTablet,
)
return checkNotNull(context.getDrawable(iconRes))
}
}
}

View File

@@ -69,7 +69,7 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
private final Context mContext;
private Resources mResources;
private final UserSwitcherController mUserSwitcherController;
private UserSwitcherController.BaseUserAdapter mAdapter;
private BaseUserSwitcherAdapter mAdapter;
private final KeyguardStateController mKeyguardStateController;
private final FalsingManager mFalsingManager;
protected final SysuiStatusBarStateController mStatusBarStateController;
@@ -171,7 +171,7 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
mUserAvatarView = mView.findViewById(R.id.kg_multi_user_avatar);
mUserAvatarViewWithBackground = mView.findViewById(
R.id.kg_multi_user_avatar_with_background);
mAdapter = new UserSwitcherController.BaseUserAdapter(mUserSwitcherController) {
mAdapter = new BaseUserSwitcherAdapter(mUserSwitcherController) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return null;

View File

@@ -16,9 +16,6 @@
package com.android.systemui.statusbar.policy;
import static com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_DISABLED_ALPHA;
import static com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_ENABLED_ALPHA;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
@@ -232,14 +229,8 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS
}
/**
* See:
* Returns {@code true} if the user switcher should be open by default on the lock screen.
*
* <ul>
* <li>{@link com.android.internal.R.bool.config_expandLockScreenUserSwitcher}</li>
* <li>{@link UserSwitcherController.SIMPLE_USER_SWITCHER_GLOBAL_SETTING}</li>
* </ul>
*
* @return true if the user switcher should be open by default on the lock screen.
* @see android.os.UserManager#isUserSwitcherEnabled()
*/
public boolean isSimpleUserSwitcher() {
@@ -436,7 +427,7 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS
}
static class KeyguardUserAdapter extends
UserSwitcherController.BaseUserAdapter implements View.OnClickListener {
BaseUserSwitcherAdapter implements View.OnClickListener {
private final Context mContext;
private final Resources mResources;
@@ -514,9 +505,9 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS
v.bind(name, drawable, item.info.id);
}
v.setActivated(item.isCurrent);
v.setDisabledByAdmin(mController.isDisabledByAdmin(item));
v.setDisabledByAdmin(getController().isDisabledByAdmin(item));
v.setEnabled(item.isSwitchToEnabled);
v.setAlpha(v.isEnabled() ? USER_SWITCH_ENABLED_ALPHA : USER_SWITCH_DISABLED_ALPHA);
UserSwitcherController.setSelectableAlpha(v);
if (item.isCurrent) {
mCurrentUserView = v;

View File

@@ -0,0 +1,182 @@
/*
* 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.policy
import android.annotation.UserIdInt
import android.content.Intent
import android.view.View
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin
import com.android.systemui.Dumpable
import com.android.systemui.qs.user.UserSwitchDialogController.DialogShower
import com.android.systemui.user.data.source.UserRecord
import com.android.systemui.user.legacyhelper.ui.LegacyUserUiHelper
import java.lang.ref.WeakReference
import kotlinx.coroutines.flow.Flow
/** Defines interface for a class that provides user switching functionality and state. */
interface UserSwitcherController : Dumpable {
/** The current list of [UserRecord]. */
val users: ArrayList<UserRecord>
/** Whether the user switcher experience should use the simple experience. */
val isSimpleUserSwitcher: Boolean
/** Require a view for jank detection */
fun init(view: View)
/** The [UserRecord] of the current user or `null` when none. */
val currentUserRecord: UserRecord?
/** The name of the current user of the device or `null`, when none is selected. */
val currentUserName: String?
/**
* Notifies that a user has been selected.
*
* This will trigger the right user journeys to create a guest user, switch users, and/or
* navigate to the correct destination.
*
* If a user with the given ID is not found, this method is a no-op.
*
* @param userId The ID of the user to switch to.
* @param dialogShower An optional [DialogShower] in case we need to show dialogs.
*/
fun onUserSelected(userId: Int, dialogShower: DialogShower?)
/** Whether it is allowed to add users while the device is locked. */
val isAddUsersFromLockScreenEnabled: Flow<Boolean>
/** Whether the guest user is configured to always be present on the device. */
val isGuestUserAutoCreated: Boolean
/** Whether the guest user is currently being reset. */
val isGuestUserResetting: Boolean
/** Creates and switches to the guest user. */
fun createAndSwitchToGuestUser(dialogShower: DialogShower?)
/** Shows the add user dialog. */
fun showAddUserDialog(dialogShower: DialogShower?)
/** Starts an activity to add a supervised user to the device. */
fun startSupervisedUserActivity()
/** Notifies when the display density or font scale has changed. */
fun onDensityOrFontScaleChanged()
/** Registers an adapter to notify when the users change. */
fun addAdapter(adapter: WeakReference<BaseUserSwitcherAdapter>)
/** Notifies the item for a user has been clicked. */
fun onUserListItemClicked(record: UserRecord, dialogShower: DialogShower?)
/**
* Removes guest user and switches to target user. The guest must be the current user and its id
* must be `guestUserId`.
*
* If `targetUserId` is `UserHandle.USER_NULL`, then create a new guest user in the foreground,
* and immediately switch to it. This is used for wiping the current guest and replacing it with
* a new one.
*
* If `targetUserId` is specified, then remove the guest in the background while switching to
* `targetUserId`.
*
* If device is configured with `config_guestUserAutoCreated`, then after guest user is removed,
* a new one is created in the background. This has no effect if `targetUserId` is
* `UserHandle.USER_NULL`.
*
* @param guestUserId id of the guest user to remove
* @param targetUserId id of the user to switch to after guest is removed. If
* `UserHandle.USER_NULL`, then switch immediately to the newly created guest user.
*/
fun removeGuestUser(@UserIdInt guestUserId: Int, @UserIdInt targetUserId: Int)
/**
* Exits guest user and switches to previous non-guest user. The guest must be the current user.
*
* @param guestUserId user id of the guest user to exit
* @param targetUserId user id of the guest user to exit, set to UserHandle#USER_NULL when
* target user id is not known
* @param forceRemoveGuestOnExit true: remove guest before switching user, false: remove guest
* only if its ephemeral, else keep guest
*/
fun exitGuestUser(
@UserIdInt guestUserId: Int,
@UserIdInt targetUserId: Int,
forceRemoveGuestOnExit: Boolean
)
/**
* Guarantee guest is present only if the device is provisioned. Otherwise, create a content
* observer to wait until the device is provisioned, then schedule the guest creation.
*/
fun schedulePostBootGuestCreation()
/** Whether keyguard is showing. */
val isKeyguardShowing: Boolean
/** Returns the [EnforcedAdmin] for the given record, or `null` if there isn't one. */
fun getEnforcedAdmin(record: UserRecord): EnforcedAdmin?
/** Returns `true` if the given record is disabled by the admin; `false` otherwise. */
fun isDisabledByAdmin(record: UserRecord): Boolean
/** Starts an activity with the given [Intent]. */
fun startActivity(intent: Intent)
/**
* Refreshes users from UserManager.
*
* The pictures are only loaded if they have not been loaded yet.
*
* @param forcePictureLoadForId forces the picture of the given user to be reloaded.
*/
fun refreshUsers(forcePictureLoadForId: Int)
/** Adds a subscriber to when user switches. */
fun addUserSwitchCallback(callback: UserSwitchCallback)
/** Removes a previously-added subscriber. */
fun removeUserSwitchCallback(callback: UserSwitchCallback)
/** Defines interface for classes that can be called back when the user is switched. */
fun interface UserSwitchCallback {
/** Notifies that the user has switched. */
fun onUserSwitched()
}
companion object {
/** Alpha value to apply to a user view in the user switcher when it's selectable. */
private const val ENABLED_ALPHA =
LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_SELECTABLE_ALPHA
/** Alpha value to apply to a user view in the user switcher when it's not selectable. */
private const val DISABLED_ALPHA =
LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_NOT_SELECTABLE_ALPHA
@JvmStatic
fun setSelectableAlpha(view: View) {
view.alpha =
if (view.isEnabled) {
ENABLED_ALPHA
} else {
DISABLED_ALPHA
}
}
}
}

View File

@@ -0,0 +1,269 @@
/*
* 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.policy
import android.content.Intent
import android.view.View
import com.android.settingslib.RestrictedLockUtils
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.qs.user.UserSwitchDialogController
import com.android.systemui.user.data.source.UserRecord
import dagger.Lazy
import java.io.PrintWriter
import java.lang.ref.WeakReference
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
/** Implementation of [UserSwitcherController]. */
class UserSwitcherControllerImpl
@Inject
constructor(
private val flags: FeatureFlags,
@Suppress("DEPRECATION") private val oldImpl: Lazy<UserSwitcherControllerOldImpl>,
) : UserSwitcherController {
private val isNewImpl: Boolean
get() = flags.isEnabled(Flags.REFACTORED_USER_SWITCHER_CONTROLLER)
private val _oldImpl: UserSwitcherControllerOldImpl
get() = oldImpl.get()
private fun notYetImplemented(): Nothing {
error("Not yet implemented!")
}
override val users: ArrayList<UserRecord>
get() =
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.users
}
override val isSimpleUserSwitcher: Boolean
get() =
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.isSimpleUserSwitcher
}
override fun init(view: View) {
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.init(view)
}
}
override val currentUserRecord: UserRecord?
get() =
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.currentUserRecord
}
override val currentUserName: String?
get() =
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.currentUserName
}
override fun onUserSelected(
userId: Int,
dialogShower: UserSwitchDialogController.DialogShower?
) {
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.onUserSelected(userId, dialogShower)
}
}
override val isAddUsersFromLockScreenEnabled: Flow<Boolean>
get() =
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.isAddUsersFromLockScreenEnabled
}
override val isGuestUserAutoCreated: Boolean
get() =
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.isGuestUserAutoCreated
}
override val isGuestUserResetting: Boolean
get() =
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.isGuestUserResetting
}
override fun createAndSwitchToGuestUser(
dialogShower: UserSwitchDialogController.DialogShower?,
) {
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.createAndSwitchToGuestUser(dialogShower)
}
}
override fun showAddUserDialog(dialogShower: UserSwitchDialogController.DialogShower?) {
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.showAddUserDialog(dialogShower)
}
}
override fun startSupervisedUserActivity() {
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.startSupervisedUserActivity()
}
}
override fun onDensityOrFontScaleChanged() {
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.onDensityOrFontScaleChanged()
}
}
override fun addAdapter(adapter: WeakReference<BaseUserSwitcherAdapter>) {
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.addAdapter(adapter)
}
}
override fun onUserListItemClicked(
record: UserRecord,
dialogShower: UserSwitchDialogController.DialogShower?,
) {
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.onUserListItemClicked(record, dialogShower)
}
}
override fun removeGuestUser(guestUserId: Int, targetUserId: Int) {
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.removeGuestUser(guestUserId, targetUserId)
}
}
override fun exitGuestUser(
guestUserId: Int,
targetUserId: Int,
forceRemoveGuestOnExit: Boolean
) {
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.exitGuestUser(guestUserId, targetUserId, forceRemoveGuestOnExit)
}
}
override fun schedulePostBootGuestCreation() {
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.schedulePostBootGuestCreation()
}
}
override val isKeyguardShowing: Boolean
get() =
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.isKeyguardShowing
}
override fun getEnforcedAdmin(record: UserRecord): RestrictedLockUtils.EnforcedAdmin? {
return if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.getEnforcedAdmin(record)
}
}
override fun isDisabledByAdmin(record: UserRecord): Boolean {
return if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.isDisabledByAdmin(record)
}
}
override fun startActivity(intent: Intent) {
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.startActivity(intent)
}
}
override fun refreshUsers(forcePictureLoadForId: Int) {
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.refreshUsers(forcePictureLoadForId)
}
}
override fun addUserSwitchCallback(callback: UserSwitcherController.UserSwitchCallback) {
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.addUserSwitchCallback(callback)
}
}
override fun removeUserSwitchCallback(callback: UserSwitcherController.UserSwitchCallback) {
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.removeUserSwitchCallback(callback)
}
}
override fun dump(pw: PrintWriter, args: Array<out String>) {
if (isNewImpl) {
notYetImplemented()
} else {
_oldImpl.dump(pw, args)
}
}
}

View File

@@ -11,9 +11,8 @@
* 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
* limitations under the License.
*/
package com.android.systemui.statusbar.policy;
import static android.os.UserManager.SWITCHABILITY_STATUS_OK;
@@ -34,10 +33,6 @@ import android.content.IntentFilter;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.ColorFilter;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -51,7 +46,6 @@ import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.view.View;
import android.view.WindowManagerGlobal;
import android.widget.BaseAdapter;
import android.widget.Toast;
import androidx.annotation.Nullable;
@@ -63,7 +57,6 @@ import com.android.internal.logging.UiEventLogger;
import com.android.internal.util.LatencyTracker;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.users.UserCreatingDialog;
import com.android.systemui.Dumpable;
import com.android.systemui.GuestResetOrExitSessionReceiver;
import com.android.systemui.GuestResumeSessionReceiver;
import com.android.systemui.R;
@@ -86,7 +79,6 @@ import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.telephony.TelephonyListenerManager;
import com.android.systemui.user.CreateUserActivity;
import com.android.systemui.user.data.source.UserRecord;
import com.android.systemui.user.legacyhelper.ui.LegacyUserUiHelper;
import com.android.systemui.util.settings.GlobalSettings;
import com.android.systemui.util.settings.SecureSettings;
@@ -106,15 +98,14 @@ import kotlinx.coroutines.flow.MutableStateFlow;
import kotlinx.coroutines.flow.StateFlowKt;
/**
* Keeps a list of all users on the device for user switching.
* Old implementation. Keeps a list of all users on the device for user switching.
*
* @deprecated This is the old implementation. Please depend on {@link UserSwitcherController}
* instead.
*/
@Deprecated
@SysUISingleton
public class UserSwitcherController implements Dumpable {
public static final float USER_SWITCH_ENABLED_ALPHA =
LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_SELECTABLE_ALPHA;
public static final float USER_SWITCH_DISABLED_ALPHA =
LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_NOT_SELECTABLE_ALPHA;
public class UserSwitcherControllerOldImpl implements UserSwitcherController {
private static final String TAG = "UserSwitcherController";
private static final boolean DEBUG = false;
@@ -123,7 +114,7 @@ public class UserSwitcherController implements Dumpable {
private static final int PAUSE_REFRESH_USERS_TIMEOUT_MS = 3000;
private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
private static final long MULTI_USER_JOURNEY_TIMEOUT = 20000l;
private static final long MULTI_USER_JOURNEY_TIMEOUT = 20000L;
private static final String INTERACTION_JANK_ADD_NEW_USER_TAG = "add_new_user";
private static final String INTERACTION_JANK_EXIT_GUEST_MODE_TAG = "exit_guest_mode";
@@ -132,7 +123,7 @@ public class UserSwitcherController implements Dumpable {
protected final UserTracker mUserTracker;
protected final UserManager mUserManager;
private final ContentObserver mSettingsObserver;
private final ArrayList<WeakReference<BaseUserAdapter>> mAdapters = new ArrayList<>();
private final ArrayList<WeakReference<BaseUserSwitcherAdapter>> mAdapters = new ArrayList<>();
@VisibleForTesting
final GuestResumeSessionReceiver mGuestResumeSessionReceiver;
@VisibleForTesting
@@ -158,7 +149,6 @@ public class UserSwitcherController implements Dumpable {
@VisibleForTesting
Dialog mAddUserDialog;
private int mLastNonGuestUser = UserHandle.USER_SYSTEM;
private boolean mResumeUserOnGuestLogout = true;
private boolean mSimpleUserSwitcher;
// When false, there won't be any visual affordance to add a new user from the keyguard even if
// the user is unlocked
@@ -187,7 +177,8 @@ public class UserSwitcherController implements Dumpable {
Collections.synchronizedList(new ArrayList<>());
@Inject
public UserSwitcherController(Context context,
public UserSwitcherControllerOldImpl(
Context context,
IActivityManager activityManager,
UserManager userManager,
UserTracker userTracker,
@@ -303,16 +294,10 @@ public class UserSwitcherController implements Dumpable {
refreshUsers(UserHandle.USER_NULL);
}
/**
* Refreshes users from UserManager.
*
* The pictures are only loaded if they have not been loaded yet.
*
* @param forcePictureLoadForId forces the picture of the given user to be reloaded.
*/
@Override
@SuppressWarnings("unchecked")
private void refreshUsers(int forcePictureLoadForId) {
if (DEBUG) Log.d(TAG, "refreshUsers(forcePictureLoadForId=" + forcePictureLoadForId+")");
public void refreshUsers(int forcePictureLoadForId) {
if (DEBUG) Log.d(TAG, "refreshUsers(forcePictureLoadForId=" + forcePictureLoadForId + ")");
if (forcePictureLoadForId != UserHandle.USER_NULL) {
mForcePictureLoadForUserId.put(forcePictureLoadForId, true);
}
@@ -323,8 +308,8 @@ public class UserSwitcherController implements Dumpable {
boolean forceAllUsers = mForcePictureLoadForUserId.get(UserHandle.USER_ALL);
SparseArray<Bitmap> bitmaps = new SparseArray<>(mUsers.size());
final int N = mUsers.size();
for (int i = 0; i < N; i++) {
final int userCount = mUsers.size();
for (int i = 0; i < userCount; i++) {
UserRecord r = mUsers.get(i);
if (r == null || r.picture == null || r.info == null || forceAllUsers
|| mForcePictureLoadForUserId.get(r.info.id)) {
@@ -431,38 +416,41 @@ public class UserSwitcherController implements Dumpable {
});
}
boolean systemCanCreateUsers() {
private boolean systemCanCreateUsers() {
return !mUserManager.hasBaseUserRestriction(
UserManager.DISALLOW_ADD_USER, UserHandle.SYSTEM);
}
boolean currentUserCanCreateUsers() {
private boolean currentUserCanCreateUsers() {
UserInfo currentUser = mUserTracker.getUserInfo();
return currentUser != null
&& (currentUser.isAdmin() || mUserTracker.getUserId() == UserHandle.USER_SYSTEM)
&& systemCanCreateUsers();
}
boolean anyoneCanCreateUsers() {
private boolean anyoneCanCreateUsers() {
return systemCanCreateUsers() && mAddUsersFromLockScreen.getValue();
}
@VisibleForTesting
boolean canCreateGuest(boolean hasExistingGuest) {
return mUserSwitcherEnabled
&& (currentUserCanCreateUsers() || anyoneCanCreateUsers())
&& !hasExistingGuest;
}
@VisibleForTesting
boolean canCreateUser() {
return mUserSwitcherEnabled
&& (currentUserCanCreateUsers() || anyoneCanCreateUsers())
&& mUserManager.canAddMoreUsers(UserManager.USER_TYPE_FULL_SECONDARY);
}
boolean createIsRestricted() {
private boolean createIsRestricted() {
return !mAddUsersFromLockScreen.getValue();
}
@VisibleForTesting
boolean canCreateSupervisedUser() {
return !TextUtils.isEmpty(mCreateSupervisedUserPackage) && canCreateUser();
}
@@ -476,7 +464,7 @@ public class UserSwitcherController implements Dumpable {
private void notifyAdapters() {
for (int i = mAdapters.size() - 1; i >= 0; i--) {
BaseUserAdapter adapter = mAdapters.get(i).get();
BaseUserSwitcherAdapter adapter = mAdapters.get(i).get();
if (adapter != null) {
adapter.notifyDataSetChanged();
} else {
@@ -485,37 +473,20 @@ public class UserSwitcherController implements Dumpable {
}
}
@Override
public boolean isSimpleUserSwitcher() {
return mSimpleUserSwitcher;
}
public void setResumeUserOnGuestLogout(boolean resume) {
mResumeUserOnGuestLogout = resume;
}
/**
* Returns whether the current user is a system user.
*/
public boolean isSystemUser() {
@VisibleForTesting
boolean isSystemUser() {
return mUserTracker.getUserId() == UserHandle.USER_SYSTEM;
}
public void removeUserId(int userId) {
if (userId == UserHandle.USER_SYSTEM) {
Log.w(TAG, "User " + userId + " could not removed.");
return;
}
if (mUserTracker.getUserId() == userId) {
switchToUserId(UserHandle.USER_SYSTEM);
}
if (mUserManager.removeUser(userId)) {
refreshUsers(UserHandle.USER_NULL);
}
}
/**
* @return UserRecord for the current user
*/
@Override
public @Nullable UserRecord getCurrentUserRecord() {
for (int i = 0; i < mUsers.size(); ++i) {
UserRecord userRecord = mUsers.get(i);
@@ -526,17 +497,7 @@ public class UserSwitcherController implements Dumpable {
return null;
}
/**
* Notifies that a user has been selected.
*
* <p>This will trigger the right user journeys to create a guest user, switch users, and/or
* navigate to the correct destination.
*
* <p>If a user with the given ID is not found, this method is a no-op.
*
* @param userId The ID of the user to switch to.
* @param dialogShower An optional {@link DialogShower} in case we need to show dialogs.
*/
@Override
public void onUserSelected(int userId, @Nullable DialogShower dialogShower) {
UserRecord userRecord = mUsers.stream()
.filter(x -> x.resolveId() == userId)
@@ -549,23 +510,23 @@ public class UserSwitcherController implements Dumpable {
onUserListItemClicked(userRecord, dialogShower);
}
/** Whether it is allowed to add users while the device is locked. */
public Flow<Boolean> getAddUsersFromLockScreen() {
@Override
public Flow<Boolean> isAddUsersFromLockScreenEnabled() {
return mAddUsersFromLockScreen;
}
/** Returns {@code true} if the guest user is configured to always be present on the device. */
@Override
public boolean isGuestUserAutoCreated() {
return mGuestUserAutoCreated;
}
/** Returns {@code true} if the guest user is currently being reset. */
@Override
public boolean isGuestUserResetting() {
return mGuestIsResetting.get();
}
@VisibleForTesting
void onUserListItemClicked(UserRecord record, DialogShower dialogShower) {
@Override
public void onUserListItemClicked(UserRecord record, DialogShower dialogShower) {
if (record.isGuest && record.info == null) {
createAndSwitchToGuestUser(dialogShower);
} else if (record.isAddUser) {
@@ -604,7 +565,7 @@ public class UserSwitcherController implements Dumpable {
switchToUserId(id);
}
protected void switchToUserId(int id) {
private void switchToUserId(int id) {
try {
if (mView != null) {
mInteractionJankMonitor.begin(InteractionJankMonitor.Configuration.Builder
@@ -621,7 +582,7 @@ public class UserSwitcherController implements Dumpable {
private void showExitGuestDialog(int id, boolean isGuestEphemeral, DialogShower dialogShower) {
int newId = UserHandle.USER_SYSTEM;
if (mResumeUserOnGuestLogout && mLastNonGuestUser != UserHandle.USER_SYSTEM) {
if (mLastNonGuestUser != UserHandle.USER_SYSTEM) {
UserInfo info = mUserManager.getUserInfo(mLastNonGuestUser);
if (info != null && info.isEnabled() && info.supportsSwitchToByUser()) {
newId = info.id;
@@ -645,9 +606,7 @@ public class UserSwitcherController implements Dumpable {
}
}
/**
* Creates and switches to the guest user.
*/
@Override
public void createAndSwitchToGuestUser(@Nullable DialogShower dialogShower) {
createGuestAsync(guestId -> {
// guestId may be USER_NULL if we haven't reloaded the user list yet.
@@ -658,9 +617,7 @@ public class UserSwitcherController implements Dumpable {
});
}
/**
* Shows the add user dialog.
*/
@Override
public void showAddUserDialog(@Nullable DialogShower dialogShower) {
if (mAddUserDialog != null && mAddUserDialog.isShowing()) {
mAddUserDialog.cancel();
@@ -677,9 +634,7 @@ public class UserSwitcherController implements Dumpable {
}
}
/**
* Starts an activity to add a supervised user to the device.
*/
@Override
public void startSupervisedUserActivity() {
final Intent intent = new Intent()
.setAction(UserManager.ACTION_CREATE_SUPERVISED_USER)
@@ -711,7 +666,7 @@ public class UserSwitcherController implements Dumpable {
public void onReceive(Context context, Intent intent) {
if (DEBUG) {
Log.v(TAG, "Broadcast: a=" + intent.getAction()
+ " user=" + intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1));
+ " user=" + intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1));
}
boolean unpauseRefreshUsers = false;
@@ -725,8 +680,8 @@ public class UserSwitcherController implements Dumpable {
final int currentId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
final UserInfo userInfo = mUserManager.getUserInfo(currentId);
final int N = mUsers.size();
for (int i = 0; i < N; i++) {
final int userCount = mUsers.size();
for (int i = 0; i < userCount; i++) {
UserRecord record = mUsers.get(i);
if (record.info == null) continue;
boolean shouldBeCurrent = record.info.id == currentId;
@@ -805,7 +760,7 @@ public class UserSwitcherController implements Dumpable {
pw.println("mGuestUserAutoCreated=" + mGuestUserAutoCreated);
}
/** Returns the name of the current user of the phone. */
@Override
public String getCurrentUserName() {
if (mUsers.isEmpty()) return null;
UserRecord item = mUsers.stream().filter(x -> x.isCurrent).findFirst().orElse(null);
@@ -814,40 +769,22 @@ public class UserSwitcherController implements Dumpable {
return item.info.name;
}
@Override
public void onDensityOrFontScaleChanged() {
refreshUsers(UserHandle.USER_ALL);
}
@VisibleForTesting
public void addAdapter(WeakReference<BaseUserAdapter> adapter) {
@Override
public void addAdapter(WeakReference<BaseUserSwitcherAdapter> adapter) {
mAdapters.add(adapter);
}
@VisibleForTesting
@Override
public ArrayList<UserRecord> getUsers() {
return mUsers;
}
/**
* Removes guest user and switches to target user. The guest must be the current user and its id
* must be {@code guestUserId}.
*
* <p>If {@code targetUserId} is {@link UserHandle#USER_NULL}, then create a new guest user in
* the foreground, and immediately switch to it. This is used for wiping the current guest and
* replacing it with a new one.
*
* <p>If {@code targetUserId} is specified, then remove the guest in the background while
* switching to {@code targetUserId}.
*
* <p>If device is configured with {@link
* com.android.internal.R.bool.config_guestUserAutoCreated}, then after guest user is removed, a
* new one is created in the background. This has no effect if {@code targetUserId} is {@link
* UserHandle#USER_NULL}.
*
* @param guestUserId id of the guest user to remove
* @param targetUserId id of the user to switch to after guest is removed. If {@link
* UserHandle#USER_NULL}, then switch immediately to the newly created guest user.
*/
@Override
public void removeGuestUser(@UserIdInt int guestUserId, @UserIdInt int targetUserId) {
UserInfo currentUser = mUserTracker.getUserInfo();
if (currentUser.id != guestUserId) {
@@ -894,18 +831,9 @@ public class UserSwitcherController implements Dumpable {
}
}
/**
* Exits guest user and switches to previous non-guest user. The guest must be the current
* user.
*
* @param guestUserId user id of the guest user to exit
* @param targetUserId user id of the guest user to exit, set to UserHandle#USER_NULL when
* target user id is not known
* @param forceRemoveGuestOnExit true: remove guest before switching user,
* false: remove guest only if its ephemeral, else keep guest
*/
@Override
public void exitGuestUser(@UserIdInt int guestUserId, @UserIdInt int targetUserId,
boolean forceRemoveGuestOnExit) {
boolean forceRemoveGuestOnExit) {
UserInfo currentUser = mUserTracker.getUserInfo();
if (currentUser.id != guestUserId) {
Log.w(TAG, "User requesting to start a new session (" + guestUserId + ")"
@@ -921,7 +849,7 @@ public class UserSwitcherController implements Dumpable {
int newUserId = UserHandle.USER_SYSTEM;
if (targetUserId == UserHandle.USER_NULL) {
// when target user is not specified switch to last non guest user
if (mResumeUserOnGuestLogout && mLastNonGuestUser != UserHandle.USER_SYSTEM) {
if (mLastNonGuestUser != UserHandle.USER_SYSTEM) {
UserInfo info = mUserManager.getUserInfo(mLastNonGuestUser);
if (info != null && info.isEnabled() && info.supportsSwitchToByUser()) {
newUserId = info.id;
@@ -959,10 +887,7 @@ public class UserSwitcherController implements Dumpable {
}
/**
* Guarantee guest is present only if the device is provisioned. Otherwise, create a content
* observer to wait until the device is provisioned, then schedule the guest creation.
*/
@Override
public void schedulePostBootGuestCreation() {
if (isDeviceAllowedToAddGuest()) {
guaranteeGuestPresent();
@@ -1014,7 +939,7 @@ public class UserSwitcherController implements Dumpable {
* @return The multi-user user ID of the newly created guest user, or
* {@link UserHandle#USER_NULL} if the guest couldn't be created.
*/
public @UserIdInt int createGuest() {
private @UserIdInt int createGuest() {
UserInfo guest;
try {
guest = mUserManager.createGuest(mContext);
@@ -1029,135 +954,27 @@ public class UserSwitcherController implements Dumpable {
return guest.id;
}
/**
* Require a view for jank detection
*/
@Override
public void init(View view) {
mView = view;
}
@VisibleForTesting
public KeyguardStateController getKeyguardStateController() {
return mKeyguardStateController;
@Override
public boolean isKeyguardShowing() {
return mKeyguardStateController.isShowing();
}
/**
* Returns the {@link EnforcedAdmin} for the given record, or {@code null} if there isn't one.
*/
@Override
@Nullable
public EnforcedAdmin getEnforcedAdmin(UserRecord record) {
return mEnforcedAdminByUserRecord.get(record);
}
/**
* Returns {@code true} if the given record is disabled by the admin; {@code false} otherwise.
*/
@Override
public boolean isDisabledByAdmin(UserRecord record) {
return mDisabledByAdmin.contains(record);
}
public static abstract class BaseUserAdapter extends BaseAdapter {
final UserSwitcherController mController;
private final KeyguardStateController mKeyguardStateController;
protected BaseUserAdapter(UserSwitcherController controller) {
mController = controller;
mKeyguardStateController = controller.getKeyguardStateController();
controller.addAdapter(new WeakReference<>(this));
}
protected ArrayList<UserRecord> getUsers() {
return mController.getUsers();
}
public int getUserCount() {
return countUsers(false);
}
@Override
public int getCount() {
return countUsers(true);
}
private int countUsers(boolean includeGuest) {
boolean keyguardShowing = mKeyguardStateController.isShowing();
final int userSize = getUsers().size();
int count = 0;
for (int i = 0; i < userSize; i++) {
if (getUsers().get(i).isGuest && !includeGuest) {
continue;
}
if (getUsers().get(i).isRestricted && keyguardShowing) {
break;
}
count++;
}
return count;
}
@Override
public UserRecord getItem(int position) {
return getUsers().get(position);
}
@Override
public long getItemId(int position) {
return position;
}
/**
* It handles click events on user list items.
*
* If the user switcher is hosted in a dialog, passing a non-null {@link DialogShower}
* will allow animation to and from the parent dialog.
*
*/
public void onUserListItemClicked(UserRecord record, @Nullable DialogShower dialogShower) {
mController.onUserListItemClicked(record, dialogShower);
}
public void onUserListItemClicked(UserRecord record) {
onUserListItemClicked(record, null);
}
public String getName(Context context, UserRecord item) {
return getName(context, item, false);
}
/**
* Returns the name for the given {@link UserRecord}.
*/
public String getName(Context context, UserRecord item, boolean isTablet) {
return LegacyUserUiHelper.getUserRecordName(
context,
item,
mController.isGuestUserAutoCreated(),
mController.isGuestUserResetting(),
isTablet);
}
protected static ColorFilter getDisabledUserAvatarColorFilter() {
ColorMatrix matrix = new ColorMatrix();
matrix.setSaturation(0f); // 0 - grayscale
return new ColorMatrixColorFilter(matrix);
}
protected static Drawable getIconDrawable(Context context, UserRecord item) {
return getIconDrawable(context, item, false);
}
protected static Drawable getIconDrawable(Context context, UserRecord item,
boolean isTablet) {
int iconRes = LegacyUserUiHelper.getUserSwitcherActionIconResourceId(
item.isAddUser, item.isGuest, item.isAddSupervisedUser, isTablet);
return context.getDrawable(iconRes);
}
public void refresh() {
mController.refreshUsers(UserHandle.USER_NULL);
}
}
private void checkIfAddUserDisallowedByAdminOnly(UserRecord record) {
EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(mContext,
UserManager.DISALLOW_ADD_USER, mUserTracker.getUserId());
@@ -1178,20 +995,17 @@ public class UserSwitcherController implements Dumpable {
defaultSimpleUserSwitcher, UserHandle.USER_SYSTEM) != 0;
}
@Override
public void startActivity(Intent intent) {
mActivityStarter.startActivity(intent, true);
}
/**
* Add a subscriber to when user switches.
*/
@Override
public void addUserSwitchCallback(UserSwitchCallback callback) {
mUserSwitchCallbacks.add(callback);
}
/**
* Remove a subscriber to when user switches.
*/
@Override
public void removeUserSwitchCallback(UserSwitchCallback callback) {
mUserSwitchCallbacks.remove(callback);
}
@@ -1218,7 +1032,7 @@ public class UserSwitcherController implements Dumpable {
// which
// helps making the transition faster.
if (!mKeyguardStateController.isShowing()) {
mHandler.post(UserSwitcherController.this::notifyAdapters);
mHandler.post(UserSwitcherControllerOldImpl.this::notifyAdapters);
} else {
notifyAdapters();
}
@@ -1367,13 +1181,4 @@ public class UserSwitcherController implements Dumpable {
}
}
/**
* Callback to for when this controller receives the intent to switch users.
*/
public interface UserSwitchCallback {
/**
* Called when user has switched.
*/
void onUserSwitched();
}
}

View File

@@ -58,6 +58,8 @@ import com.android.systemui.statusbar.policy.SecurityController;
import com.android.systemui.statusbar.policy.SecurityControllerImpl;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.UserSwitcherControllerImpl;
import com.android.systemui.statusbar.policy.WalletController;
import com.android.systemui.statusbar.policy.WalletControllerImpl;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -196,4 +198,8 @@ public interface StatusBarPolicyModule {
static DataSaverController provideDataSaverController(NetworkController networkController) {
return networkController.getDataSaverController();
}
/** Binds {@link UserSwitcherController} to its implementation. */
@Binds
UserSwitcherController bindUserSwitcherController(UserSwitcherControllerImpl impl);
}

View File

@@ -53,10 +53,8 @@ import com.android.systemui.flags.Flags
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.FalsingManager.LOW_PENALTY
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.policy.BaseUserSwitcherAdapter
import com.android.systemui.statusbar.policy.UserSwitcherController
import com.android.systemui.statusbar.policy.UserSwitcherController.BaseUserAdapter
import com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_DISABLED_ALPHA
import com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_ENABLED_ALPHA
import com.android.systemui.user.data.source.UserRecord
import com.android.systemui.user.ui.binder.UserSwitcherViewBinder
import com.android.systemui.user.ui.viewmodel.UserSwitcherViewModel
@@ -66,10 +64,10 @@ import kotlin.math.ceil
private const val USER_VIEW = "user_view"
/**
* Support a fullscreen user switcher
*/
open class UserSwitcherActivity @Inject constructor(
/** Support a fullscreen user switcher */
open class UserSwitcherActivity
@Inject
constructor(
private val userSwitcherController: UserSwitcherController,
private val broadcastDispatcher: BroadcastDispatcher,
private val falsingCollector: FalsingCollector,
@@ -86,11 +84,12 @@ open class UserSwitcherActivity @Inject constructor(
private lateinit var addButton: View
private var addUserRecords = mutableListOf<UserRecord>()
private val onBackCallback = OnBackInvokedCallback { finish() }
private val userSwitchedCallback: UserTracker.Callback = object : UserTracker.Callback {
override fun onUserChanged(newUser: Int, userContext: Context) {
finish()
private val userSwitchedCallback: UserTracker.Callback =
object : UserTracker.Callback {
override fun onUserChanged(newUser: Int, userContext: Context) {
finish()
}
}
}
// When the add users options become available, insert another option to manage users
private val manageUserRecord =
UserRecord(
@@ -114,13 +113,14 @@ open class UserSwitcherActivity @Inject constructor(
@VisibleForTesting
fun createActivity() {
setContentView(R.layout.user_switcher_fullscreen)
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)
window.decorView.systemUiVisibility =
(View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)
if (isUsingModernArchitecture()) {
Log.d(TAG, "Using modern architecture.")
val viewModel = ViewModelProvider(
this, viewModelFactory.get())[UserSwitcherViewModel::class.java]
val viewModel =
ViewModelProvider(this, viewModelFactory.get())[UserSwitcherViewModel::class.java]
UserSwitcherViewBinder.bind(
view = requireViewById(R.id.user_switcher_root),
viewModel = viewModel,
@@ -136,27 +136,23 @@ open class UserSwitcherActivity @Inject constructor(
parent = requireViewById<UserSwitcherRootView>(R.id.user_switcher_root)
parent.touchHandler = object : Gefingerpoken {
override fun onTouchEvent(ev: MotionEvent?): Boolean {
falsingCollector.onTouchEvent(ev)
return false
parent.touchHandler =
object : Gefingerpoken {
override fun onTouchEvent(ev: MotionEvent?): Boolean {
falsingCollector.onTouchEvent(ev)
return false
}
}
}
requireViewById<View>(R.id.cancel).apply {
setOnClickListener {
_ -> finish()
}
}
requireViewById<View>(R.id.cancel).apply { setOnClickListener { _ -> finish() } }
addButton = requireViewById<View>(R.id.add).apply {
setOnClickListener {
_ -> showPopupMenu()
}
}
addButton =
requireViewById<View>(R.id.add).apply { setOnClickListener { _ -> showPopupMenu() } }
onBackInvokedDispatcher.registerOnBackInvokedCallback(
OnBackInvokedDispatcher.PRIORITY_DEFAULT, onBackCallback)
OnBackInvokedDispatcher.PRIORITY_DEFAULT,
onBackCallback
)
userSwitcherController.init(parent)
initBroadcastReceiver()
@@ -169,25 +165,30 @@ open class UserSwitcherActivity @Inject constructor(
val items = mutableListOf<UserRecord>()
addUserRecords.forEach { items.add(it) }
var popupMenuAdapter = ItemAdapter(
this,
R.layout.user_switcher_fullscreen_popup_item,
layoutInflater,
{ item: UserRecord -> adapter.getName(this@UserSwitcherActivity, item, true) },
{ item: UserRecord -> adapter.findUserIcon(item, true).mutate().apply {
setTint(resources.getColor(
R.color.user_switcher_fullscreen_popup_item_tint,
getTheme()
))
} }
)
var popupMenuAdapter =
ItemAdapter(
this,
R.layout.user_switcher_fullscreen_popup_item,
layoutInflater,
{ item: UserRecord -> adapter.getName(this@UserSwitcherActivity, item, true) },
{ item: UserRecord ->
adapter.findUserIcon(item, true).mutate().apply {
setTint(
resources.getColor(
R.color.user_switcher_fullscreen_popup_item_tint,
getTheme()
)
)
}
}
)
popupMenuAdapter.addAll(items)
popupMenu = UserSwitcherPopupMenu(this).apply {
setAnchorView(addButton)
setAdapter(popupMenuAdapter)
setOnItemClickListener {
parent: AdapterView<*>, view: View, pos: Int, id: Long ->
popupMenu =
UserSwitcherPopupMenu(this).apply {
setAnchorView(addButton)
setAdapter(popupMenuAdapter)
setOnItemClickListener { parent: AdapterView<*>, view: View, pos: Int, id: Long ->
if (falsingManager.isFalseTap(LOW_PENALTY) || !view.isEnabled()) {
return@setOnItemClickListener
}
@@ -206,10 +207,10 @@ open class UserSwitcherActivity @Inject constructor(
if (!item.isAddUser) {
this@UserSwitcherActivity.finish()
}
}
}
show()
}
show()
}
}
private fun buildUserViews() {
@@ -227,8 +228,8 @@ open class UserSwitcherActivity @Inject constructor(
val totalWidth = parent.width
val userViewCount = adapter.getTotalUserViews()
val maxColumns = getMaxColumns(userViewCount)
val horizontalGap = resources
.getDimensionPixelSize(R.dimen.user_switcher_fullscreen_horizontal_gap)
val horizontalGap =
resources.getDimensionPixelSize(R.dimen.user_switcher_fullscreen_horizontal_gap)
val totalWidthOfHorizontalGap = (maxColumns - 1) * horizontalGap
val maxWidgetDiameter = (totalWidth - totalWidthOfHorizontalGap) / maxColumns
@@ -299,14 +300,15 @@ open class UserSwitcherActivity @Inject constructor(
}
private fun initBroadcastReceiver() {
broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.getAction()
if (Intent.ACTION_SCREEN_OFF.equals(action)) {
finish()
broadcastReceiver =
object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.getAction()
if (Intent.ACTION_SCREEN_OFF.equals(action)) {
finish()
}
}
}
}
val filter = IntentFilter()
filter.addAction(Intent.ACTION_SCREEN_OFF)
@@ -322,9 +324,7 @@ open class UserSwitcherActivity @Inject constructor(
return flags.isEnabled(Flags.MODERN_USER_SWITCHER_ACTIVITY)
}
/**
* Provides views to populate the option menu.
*/
/** Provides views to populate the option menu. */
private class ItemAdapter(
val parentContext: Context,
val resource: Int,
@@ -337,43 +337,27 @@ open class UserSwitcherActivity @Inject constructor(
val item = getItem(position)
val view = convertView ?: layoutInflater.inflate(resource, parent, false)
view.requireViewById<ImageView>(R.id.icon).apply {
setImageDrawable(iconGetter(item))
}
view.requireViewById<TextView>(R.id.text).apply {
setText(textGetter(item))
}
view.requireViewById<ImageView>(R.id.icon).apply { setImageDrawable(iconGetter(item)) }
view.requireViewById<TextView>(R.id.text).apply { setText(textGetter(item)) }
return view
}
}
private inner class UserAdapter : BaseUserAdapter(userSwitcherController) {
private inner class UserAdapter : BaseUserSwitcherAdapter(userSwitcherController) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val item = getItem(position)
var view = convertView as ViewGroup?
if (view == null) {
view = layoutInflater.inflate(
R.layout.user_switcher_fullscreen_item,
parent,
false
) as ViewGroup
}
(view.getChildAt(0) as ImageView).apply {
setImageDrawable(getDrawable(item))
}
(view.getChildAt(1) as TextView).apply {
setText(getName(getContext(), item))
view =
layoutInflater.inflate(R.layout.user_switcher_fullscreen_item, parent, false)
as ViewGroup
}
(view.getChildAt(0) as ImageView).apply { setImageDrawable(getDrawable(item)) }
(view.getChildAt(1) as TextView).apply { setText(getName(getContext(), item)) }
view.setEnabled(item.isSwitchToEnabled)
view.setAlpha(
if (view.isEnabled()) {
USER_SWITCH_ENABLED_ALPHA
} else {
USER_SWITCH_DISABLED_ALPHA
}
)
UserSwitcherController.setSelectableAlpha(view)
view.setTag(USER_VIEW)
return view
}
@@ -401,23 +385,20 @@ open class UserSwitcherActivity @Inject constructor(
}
fun getTotalUserViews(): Int {
return users.count { item ->
!doNotRenderUserView(item)
}
return users.count { item -> !doNotRenderUserView(item) }
}
fun doNotRenderUserView(item: UserRecord): Boolean {
return item.isAddUser ||
item.isAddSupervisedUser ||
item.isGuest && item.info == null
return item.isAddUser || item.isAddSupervisedUser || item.isGuest && item.info == null
}
private fun getDrawable(item: UserRecord): Drawable {
var drawable = if (item.isGuest) {
getDrawable(R.drawable.ic_account_circle)
} else {
findUserIcon(item)
}
var drawable =
if (item.isGuest) {
getDrawable(R.drawable.ic_account_circle)
} else {
findUserIcon(item)
}
drawable.mutate()
if (!item.isCurrent && !item.isSwitchToEnabled) {
@@ -429,16 +410,16 @@ open class UserSwitcherActivity @Inject constructor(
)
}
val ld = getDrawable(R.drawable.user_switcher_icon_large).mutate()
as LayerDrawable
if (item == userSwitcherController.getCurrentUserRecord()) {
val ld = getDrawable(R.drawable.user_switcher_icon_large).mutate() as LayerDrawable
if (item == userSwitcherController.currentUserRecord) {
(ld.findDrawableByLayerId(R.id.ring) as GradientDrawable).apply {
val stroke = resources
.getDimensionPixelSize(R.dimen.user_switcher_icon_selected_width)
val color = Utils.getColorAttrDefaultColor(
this@UserSwitcherActivity,
com.android.internal.R.attr.colorAccentPrimary
)
val stroke =
resources.getDimensionPixelSize(R.dimen.user_switcher_icon_selected_width)
val color =
Utils.getColorAttrDefaultColor(
this@UserSwitcherActivity,
com.android.internal.R.attr.colorAccentPrimary
)
setStroke(stroke, color)
}

View File

@@ -99,7 +99,7 @@ constructor(
override val actions: Flow<List<UserActionModel>> =
userRecords.map { records -> records.filter { it.isNotUser() }.map { it.toActionModel() } }
override val isActionableWhenLocked: Flow<Boolean> = controller.addUsersFromLockScreen
override val isActionableWhenLocked: Flow<Boolean> = controller.isAddUsersFromLockScreenEnabled
override val isGuestUserAutoCreated: Boolean = controller.isGuestUserAutoCreated

View File

@@ -116,9 +116,7 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
when(mUserSwitcherController.getCurrentUserName()).thenReturn("Test User");
when(mUserSwitcherController.getKeyguardStateController())
.thenReturn(mKeyguardStateController);
when(mKeyguardStateController.isShowing()).thenReturn(true);
when(mUserSwitcherController.isKeyguardShowing()).thenReturn(true);
mScreenWidth = getUiDevice().getDisplayWidth();
mFakeMeasureSpec = View

View File

@@ -34,14 +34,14 @@ 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.Mockito.`when`
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper
@SmallTest
class StatusBarUserSwitcherControllerTest : SysuiTestCase() {
class StatusBarUserSwitcherControllerOldImplTest : SysuiTestCase() {
@Mock
private lateinit var tracker: StatusBarUserInfoTracker

View File

@@ -0,0 +1,264 @@
/*
* 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.policy
import android.content.pm.UserInfo
import android.graphics.Bitmap
import android.os.UserHandle
import android.view.View
import android.view.ViewGroup
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.qs.user.UserSwitchDialogController
import com.android.systemui.user.data.source.UserRecord
import com.android.systemui.util.mockito.kotlinArgumentCaptor
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import java.lang.ref.WeakReference
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(JUnit4::class)
class BaseUserSwitcherAdapterTest : SysuiTestCase() {
@Mock private lateinit var controller: UserSwitcherController
private lateinit var underTest: BaseUserSwitcherAdapter
private lateinit var users: ArrayList<UserRecord>
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
users =
ArrayList(
listOf(
createUserRecord(
id = 0,
picture = mock(),
isSelected = true,
isGuest = false,
),
createUserRecord(
id = 1,
picture = mock(),
isSelected = false,
isGuest = false,
),
createUserRecord(
id = UserHandle.USER_NULL,
picture = null,
isSelected = false,
isGuest = true,
),
)
)
whenever(controller.users).thenAnswer { users }
underTest =
object : BaseUserSwitcherAdapter(controller) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
return mock()
}
}
}
@Test
fun `Adds self to controller in constructor`() {
val captor = kotlinArgumentCaptor<WeakReference<BaseUserSwitcherAdapter>>()
verify(controller).addAdapter(captor.capture())
assertThat(captor.value.get()).isEqualTo(underTest)
}
@Test
fun count() {
assertThat(underTest.count).isEqualTo(users.size)
}
@Test
fun `count - ignores restricted users when device is locked`() {
whenever(controller.isKeyguardShowing).thenReturn(true)
users =
ArrayList(
listOf(
createUserRecord(
id = 0,
picture = mock(),
isSelected = true,
isGuest = false,
isRestricted = false,
),
createUserRecord(
id = 1,
picture = mock(),
isSelected = false,
isGuest = false,
isRestricted = true, // this one will be ignored.
),
createUserRecord(
id = UserHandle.USER_NULL,
picture = null,
isSelected = false,
isGuest = true,
),
)
)
assertThat(underTest.count).isEqualTo(users.size - 1)
}
@Test
fun `count - does not ignore restricted users when device is not locked`() {
whenever(controller.isKeyguardShowing).thenReturn(false)
users =
ArrayList(
listOf(
createUserRecord(
id = 0,
picture = mock(),
isSelected = true,
isGuest = false,
isRestricted = false,
),
createUserRecord(
id = 1,
picture = mock(),
isSelected = false,
isGuest = false,
isRestricted = true,
),
createUserRecord(
id = UserHandle.USER_NULL,
picture = null,
isSelected = false,
isGuest = true,
),
)
)
assertThat(underTest.count).isEqualTo(users.size)
}
@Test
fun getItem() {
assertThat((0 until underTest.count).map { position -> underTest.getItem(position) })
.isEqualTo(users)
}
@Test
fun getItemId() {
(0 until underTest.count).map { position ->
assertThat(underTest.getItemId(position)).isEqualTo(position)
}
}
@Test
fun onUserListItemClicked() {
val userRecord = users[users.size / 2]
val dialogShower: UserSwitchDialogController.DialogShower = mock()
underTest.onUserListItemClicked(userRecord, dialogShower)
verify(controller).onUserListItemClicked(userRecord, dialogShower)
}
@Test
fun `getName - non guest - returns real name`() {
val userRecord =
createUserRecord(
id = 1,
picture = mock(),
)
assertThat(underTest.getName(context, userRecord)).isEqualTo(userRecord.info?.name)
}
@Test
fun `getName - guest and selected - returns exit guest action name`() {
val expected = "Exit guest"
context.orCreateTestableResources.addOverride(
com.android.settingslib.R.string.guest_exit_quick_settings_button,
expected,
)
val userRecord =
createUserRecord(
id = 2,
picture = null,
isGuest = true,
isSelected = true,
)
assertThat(underTest.getName(context, userRecord)).isEqualTo(expected)
}
@Test
fun `getName - guest and not selected - returns enter guest action name`() {
val expected = "Guest"
context.orCreateTestableResources.addOverride(
com.android.internal.R.string.guest_name,
expected,
)
val userRecord =
createUserRecord(
id = 2,
picture = null,
isGuest = true,
isSelected = false,
)
assertThat(underTest.getName(context, userRecord)).isEqualTo("Guest")
}
@Test
fun refresh() {
underTest.refresh()
verify(controller).refreshUsers(UserHandle.USER_NULL)
}
private fun createUserRecord(
id: Int,
picture: Bitmap? = null,
isSelected: Boolean = false,
isGuest: Boolean = false,
isAction: Boolean = false,
isRestricted: Boolean = false,
): UserRecord {
return UserRecord(
info =
if (isAction) {
null
} else {
UserInfo(id, "name$id", 0)
},
picture = picture,
isCurrent = isSelected,
isGuest = isGuest,
isRestricted = isRestricted,
)
}
}

View File

@@ -38,9 +38,9 @@ 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.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@SmallTest
@@ -102,8 +102,7 @@ class KeyguardQsUserSwitchControllerTest : SysuiTestCase() {
ViewUtils.attachView(view)
testableLooper.processAllMessages()
`when`(userSwitcherController.keyguardStateController).thenReturn(keyguardStateController)
`when`(userSwitcherController.keyguardStateController.isShowing).thenReturn(true)
`when`(userSwitcherController.isKeyguardShowing).thenReturn(true)
`when`(keyguardStateController.isShowing).thenReturn(true)
`when`(keyguardStateController.isKeyguardGoingAway).thenReturn(false)
keyguardQsUserSwitchController.init()

View File

@@ -86,7 +86,7 @@ import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@SmallTest
class UserSwitcherControllerTest : SysuiTestCase() {
class UserSwitcherControllerOldImplTest : SysuiTestCase() {
@Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var activityManager: IActivityManager
@Mock private lateinit var deviceProvisionedController: DeviceProvisionedController
@@ -118,7 +118,7 @@ class UserSwitcherControllerTest : SysuiTestCase() {
private lateinit var longRunningExecutor: FakeExecutor
private lateinit var uiExecutor: FakeExecutor
private lateinit var uiEventLogger: UiEventLoggerFake
private lateinit var userSwitcherController: UserSwitcherController
private lateinit var userSwitcherController: UserSwitcherControllerOldImpl
private lateinit var picture: Bitmap
private val ownerId = UserHandle.USER_SYSTEM
private val ownerInfo = UserInfo(ownerId, "Owner", null,
@@ -205,7 +205,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
}
private fun setupController() {
userSwitcherController = UserSwitcherController(
userSwitcherController =
UserSwitcherControllerOldImpl(
mContext,
activityManager,
userManager,
@@ -230,7 +231,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
dumpManager,
dialogLaunchAnimator,
guestResumeSessionReceiver,
guestResetOrExitSessionReceiver)
guestResetOrExitSessionReceiver
)
userSwitcherController.init(notificationShadeWindowView)
}

View File

@@ -60,7 +60,7 @@ class UserRepositoryImplTest : SysuiTestCase() {
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
whenever(controller.addUsersFromLockScreen).thenReturn(MutableStateFlow(false))
whenever(controller.isAddUsersFromLockScreenEnabled).thenReturn(MutableStateFlow(false))
whenever(controller.isGuestUserAutoCreated).thenReturn(false)
whenever(controller.isGuestUserResetting).thenReturn(false)