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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user