Revert "Improve multi user settings screen"
This reverts commit d19dc306ddbb0289063acf860d78a7c194b7a6d6.
Reason for revert: this CL made Settings the test cases called shadowUserManager.hasUserRestriction()
https://sponge.corp.google.com/target?show=FAILED&sortBy=STATUS&id=07150153-ccb7-4215-a9f8-eed31e44c66f&target=RunSettingsRoboTests1-test-output
Bug: 142798722
Change-Id: I3937a07ee35a472cadd6db8cd0177e08e63516a4
diff --git a/res/drawable/ic_add_40dp.xml b/res/drawable/ic_add_40dp.xml
deleted file mode 100644
index 7245823..0000000
--- a/res/drawable/ic_add_40dp.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<!--
- ~ Copyright (C) 2020 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.
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="40dp"
- android:height="40dp"
- android:viewportWidth="20"
- android:viewportHeight="20"
- android:tint="?android:attr/colorControlNormal">
-
- <group
- android:scaleX="0.5"
- android:scaleY="0.5"
- android:pivotX="8"
- android:pivotY="8">
-
- <path
- android:fillColor="@android:color/white"
- android:pathData="M20,13h-7v7h-2v-7H4v-2h7V4h2v7h7V13z"/>
-
- </group>
-
-</vector>
-
diff --git a/res/drawable/ic_phone.xml b/res/drawable/ic_phone.xml
deleted file mode 100644
index 28f47fd..0000000
--- a/res/drawable/ic_phone.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<!--
- ~ Copyright (C) 2020 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.
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal"
- android:autoMirrored="true">
- <path
- android:fillColor="#FF000000"
- android:pathData="M6.62,10.79c1.44,2.83 3.76,5.14 6.59,6.59l2.2,-2.2c0.27,-0.27 0.67,-0.36
- 1.02,-0.24 1.12,0.37 2.33,0.57 3.57,0.57 0.55,0 1,0.45 1,1V20c0,0.55 -0.45,1 -1,1
- -9.39,0 -17,-7.61 -17,-17 0,-0.55 0.45,-1 1,-1h3.5c0.55,0 1,0.45 1,1 0,1.25 0.2,2.45
- 0.57,3.57 0.11,0.35 0.03,0.74 -0.25,1.02l-2.2,2.2z"/>
-</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_swap.xml b/res/drawable/ic_swap.xml
deleted file mode 100644
index 1c43d97..0000000
--- a/res/drawable/ic_swap.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
- ~ Copyright (C) 2020 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.
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal">
- <path
- android:pathData="M6.99,11L3,15l3.99,4v-3H14v-2H6.99v-3zM21,9l-3.99,-4v3H10v2h7.01v3L21,9z"
- android:fillColor="#000000"/>
-</vector>
diff --git a/res/layout/restricted_preference_user_delete_widget.xml b/res/layout/restricted_preference_user_delete_widget.xml
new file mode 100644
index 0000000..71f1dd7
--- /dev/null
+++ b/res/layout/restricted_preference_user_delete_widget.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Used by UserPreference to show the trash icon -->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <include layout="@layout/restricted_icon" />
+
+ <LinearLayout android:id="@+id/user_delete_widget"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
+ <View
+ android:id="@+id/divider_manage"
+ android:layout_width="2dip"
+ android:layout_height="match_parent"
+ android:layout_marginTop="5dip"
+ android:layout_marginBottom="5dip"
+ android:background="@android:drawable/divider_horizontal_dark" />
+ <ImageView
+ android:id="@+id/manage_user"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:paddingStart="16dip"
+ android:paddingEnd="16dip"
+ android:src="@drawable/ic_settings_accent"
+ android:contentDescription="@string/settings_label"
+ android:layout_gravity="center"
+ android:background="?android:attr/selectableItemBackground" />
+ <View
+ android:id="@+id/divider_delete"
+ android:layout_width="2dip"
+ android:layout_height="match_parent"
+ android:layout_marginTop="5dip"
+ android:layout_marginBottom="5dip"
+ android:background="@android:drawable/divider_horizontal_dark" />
+ <ImageView
+ android:id="@+id/trash_user"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:paddingStart="16dip"
+ android:paddingEnd="16dip"
+ android:src="@drawable/ic_delete"
+ android:contentDescription="@string/user_delete_user_description"
+ android:layout_gravity="center"
+ android:background="?android:attr/selectableItemBackground" />
+ </LinearLayout>
+</merge>
\ No newline at end of file
diff --git a/res/layout/user_info_header.xml b/res/layout/user_info_header.xml
index bfdf3fc..5135e0e 100644
--- a/res/layout/user_info_header.xml
+++ b/res/layout/user_info_header.xml
@@ -15,7 +15,6 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
@@ -46,7 +45,8 @@
android:layout_gravity="center"
android:minWidth="48dp"
android:scaleType="centerInside"
- android:layout_marginEnd="@*android:dimen/preference_item_padding_inner"/>
+ android:layout_marginEnd="@*android:dimen/preference_item_padding_inner"
+ />
</LinearLayout>
<RelativeLayout
android:layout_width="wrap_content"
@@ -60,7 +60,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
- tools:text="Richard"
android:textAppearance="?android:attr/textAppearanceMedium"
android:ellipsize="marquee"
android:fadingEdge="horizontal"/>
@@ -89,40 +88,6 @@
android:layout_gravity="center"
android:background="?android:attr/selectableItemBackground" />
</LinearLayout>
-
- <LinearLayout
- android:id="@+id/switch_pref"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:visibility="gone"
- tools:visibility="visible"
- android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:background="?android:attr/selectableItemBackground" >
-
- <ImageView
- android:id="@+id/switchIcon"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:layout_gravity="center"
- android:src="@drawable/ic_swap"
- android:minWidth="48dp"
- android:scaleType="centerInside"
- android:layout_marginEnd="@*android:dimen/preference_item_padding_inner"/>
-
- <TextView
- android:id="@+id/switchTitle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- tools:text="Switch to Richard"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:ellipsize="marquee"
- android:fadingEdge="horizontal"/>
-
- </LinearLayout>
-
<View android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@color/divider_color" />
diff --git a/res/xml/user_details_settings.xml b/res/xml/user_details_settings.xml
index d336395..09154c4 100644
--- a/res/xml/user_details_settings.xml
+++ b/res/xml/user_details_settings.xml
@@ -17,17 +17,12 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto">
-
- <com.android.settingslib.RestrictedPreference
- android:key="switch_user"
- android:icon="@drawable/ic_swap" />
<SwitchPreference
android:key="enable_calling"
- android:icon="@drawable/ic_phone"
android:title="@string/user_enable_calling_sms" />
<com.android.settingslib.RestrictedPreference
android:key="remove_user"
- android:icon="@drawable/ic_delete"
+ android:title="@string/user_remove_user"
settings:userRestriction="no_remove_user"
settings:useAdminDisabledSummary="true" />
diff --git a/res/xml/user_settings.xml b/res/xml/user_settings.xml
index 7726a18..eb8803b 100644
--- a/res/xml/user_settings.xml
+++ b/res/xml/user_settings.xml
@@ -28,14 +28,9 @@
</PreferenceCategory>
<com.android.settingslib.RestrictedPreference
- android:key="guest_add"
- android:title="@string/guest_new_guest"
- android:order="15"/>
-
- <com.android.settingslib.RestrictedPreference
android:key="user_add"
android:title="@string/user_add_user_or_profile_menu"
- android:icon="@drawable/ic_add_40dp"
+ android:icon="@drawable/ic_add_24dp"
android:order="20"/>
<com.android.settingslib.RestrictedSwitchPreference
diff --git a/src/com/android/settings/users/AppRestrictionsFragment.java b/src/com/android/settings/users/AppRestrictionsFragment.java
index 1caf49c..7b15e8a 100644
--- a/src/com/android/settings/users/AppRestrictionsFragment.java
+++ b/src/com/android/settings/users/AppRestrictionsFragment.java
@@ -97,15 +97,8 @@
/** Key for extra passed in from calling fragment to indicate if this is a newly created user */
public static final String EXTRA_NEW_USER = "new_user";
- /**
- * Key for extra passed in from calling fragment to indicate if
- * switch to user should be shown
- */
- public static final String EXTRA_SHOW_SWITCH_USER = "enable_switch";
-
private boolean mFirstTime = true;
private boolean mNewUser;
- protected boolean mShowSwitchUser;
private boolean mAppListChanged;
protected boolean mRestrictedProfile;
@@ -226,7 +219,6 @@
mUser = new UserHandle(args.getInt(EXTRA_USER_ID));
}
mNewUser = args.getBoolean(EXTRA_NEW_USER, false);
- mShowSwitchUser = args.getBoolean(EXTRA_SHOW_SWITCH_USER, false);
}
}
diff --git a/src/com/android/settings/users/RestrictedProfileSettings.java b/src/com/android/settings/users/RestrictedProfileSettings.java
index 44657cf..57c0d02 100644
--- a/src/com/android/settings/users/RestrictedProfileSettings.java
+++ b/src/com/android/settings/users/RestrictedProfileSettings.java
@@ -16,7 +16,6 @@
package com.android.settings.users;
-import android.app.ActivityManager;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.DialogInterface;
@@ -24,10 +23,7 @@
import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
-import android.os.RemoteException;
import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
@@ -40,7 +36,6 @@
public class RestrictedProfileSettings extends AppRestrictionsFragment
implements EditUserInfoController.OnContentChangedCallback {
- private static final String TAG = RestrictedProfileSettings.class.getSimpleName();
public static final String FILE_PROVIDER_AUTHORITY = "com.android.settings.files";
static final int DIALOG_ID_EDIT_USER_INFO = 1;
private static final int DIALOG_CONFIRM_REMOVE = 2;
@@ -49,8 +44,6 @@
private ImageView mUserIconView;
private TextView mUserNameView;
private ImageView mDeleteButton;
- private View mSwitchUserView;
- private TextView mSwitchTitle;
private EditUserInfoController mEditUserInfoController =
new EditUserInfoController();
@@ -74,11 +67,6 @@
mUserNameView = (TextView) mHeaderView.findViewById(android.R.id.title);
mDeleteButton = (ImageView) mHeaderView.findViewById(R.id.delete);
mDeleteButton.setOnClickListener(this);
-
- mSwitchTitle = mHeaderView.findViewById(R.id.switchTitle);
- mSwitchUserView = mHeaderView.findViewById(R.id.switch_pref);
- mSwitchUserView.setOnClickListener(v -> switchUser());
-
// This is going to bind the preferences.
super.onActivityCreated(savedInstanceState);
}
@@ -92,6 +80,7 @@
@Override
public void onResume() {
super.onResume();
+
// Check if user still exists
UserInfo info = Utils.getExistingUser(mUserManager, mUser);
if (info == null) {
@@ -100,16 +89,6 @@
((TextView) mHeaderView.findViewById(android.R.id.title)).setText(info.name);
((ImageView) mHeaderView.findViewById(android.R.id.icon)).setImageDrawable(
com.android.settingslib.Utils.getUserIcon(getActivity(), mUserManager, info));
-
- boolean canSwitchUser =
- mUserManager.getUserSwitchability() == UserManager.SWITCHABILITY_STATUS_OK;
- if (mShowSwitchUser && canSwitchUser) {
- mSwitchUserView.setVisibility(View.VISIBLE);
- mSwitchTitle.setText(getString(com.android.settingslib.R.string.user_switch_to_user,
- info.name));
- } else {
- mSwitchUserView.setVisibility(View.GONE);
- }
}
}
@@ -179,16 +158,6 @@
});
}
- private void switchUser() {
- try {
- ActivityManager.getService().switchUser(mUser.getIdentifier());
- } catch (RemoteException re) {
- Log.e(TAG, "Error while switching to other user.");
- } finally {
- finishFragment();
- }
- }
-
@Override
public void onPhotoChanged(UserHandle user, Drawable photo) {
mUserIconView.setImageDrawable(photo);
diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java
index 2696ddc..371c152 100644
--- a/src/com/android/settings/users/UserDetailsSettings.java
+++ b/src/com/android/settings/users/UserDetailsSettings.java
@@ -16,63 +16,55 @@
package com.android.settings.users;
-import static android.os.UserHandle.USER_NULL;
-
-import android.app.ActivityManager;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.pm.UserInfo;
import android.os.Bundle;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
-import android.util.Log;
-import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.SwitchPreference;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.Utils;
-import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
import java.util.List;
/**
- * Settings screen for configuring, deleting or switching to a specific user.
- * It is shown when you tap on a user in the user management (UserSettings) screen.
+ * Settings screen for configuring a specific user. It can contain user restrictions
+ * and deletion controls. It is shown when you tap on the settings icon in the
+ * user management (UserSettings) screen.
*
* Arguments to this fragment must include the userId of the user (in EXTRA_USER_ID) for whom
- * to display controls.
+ * to display controls, or should contain the EXTRA_USER_GUEST = true.
*/
public class UserDetailsSettings extends SettingsPreferenceFragment
implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener {
private static final String TAG = UserDetailsSettings.class.getSimpleName();
- private static final String KEY_SWITCH_USER = "switch_user";
private static final String KEY_ENABLE_TELEPHONY = "enable_calling";
private static final String KEY_REMOVE_USER = "remove_user";
/** Integer extra containing the userId to manage */
static final String EXTRA_USER_ID = "user_id";
+ /** Boolean extra to indicate guest preferences */
+ static final String EXTRA_USER_GUEST = "guest_user";
private static final int DIALOG_CONFIRM_REMOVE = 1;
private static final int DIALOG_CONFIRM_ENABLE_CALLING = 2;
private static final int DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS = 3;
private UserManager mUserManager;
- @VisibleForTesting
- Preference mSwitchUserPref;
private SwitchPreference mPhonePref;
- @VisibleForTesting
- Preference mRemoveUserPref;
+ private Preference mRemoveUserPref;
- @VisibleForTesting
- UserInfo mUserInfo;
+ private UserInfo mUserInfo;
+ private boolean mGuestUser;
private Bundle mDefaultGuestRestrictions;
@Override
@@ -86,28 +78,46 @@
final Context context = getActivity();
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+
addPreferencesFromResource(R.xml.user_details_settings);
+ mPhonePref = (SwitchPreference) findPreference(KEY_ENABLE_TELEPHONY);
+ mRemoveUserPref = findPreference(KEY_REMOVE_USER);
- initialize(context, getArguments());
- }
+ mGuestUser = getArguments().getBoolean(EXTRA_USER_GUEST, false);
- @Override
- public void onResume() {
- super.onResume();
- mSwitchUserPref.setEnabled(canSwitchUserNow());
+ if (!mGuestUser) {
+ // Regular user. Get the user id from the caller.
+ final int userId = getArguments().getInt(EXTRA_USER_ID, -1);
+ if (userId == -1) {
+ throw new RuntimeException("Arguments to this fragment must contain the user id");
+ }
+ mUserInfo = mUserManager.getUserInfo(userId);
+ mPhonePref.setChecked(!mUserManager.hasUserRestriction(
+ UserManager.DISALLOW_OUTGOING_CALLS, new UserHandle(userId)));
+ mRemoveUserPref.setOnPreferenceClickListener(this);
+ } else {
+ // These are not for an existing user, just general Guest settings.
+ removePreference(KEY_REMOVE_USER);
+ // Default title is for calling and SMS. Change to calling-only here
+ mPhonePref.setTitle(R.string.user_enable_calling);
+ mDefaultGuestRestrictions = mUserManager.getDefaultGuestRestrictions();
+ mPhonePref.setChecked(
+ !mDefaultGuestRestrictions.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
+ }
+ if (RestrictedLockUtilsInternal.hasBaseUserRestriction(context,
+ UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId())) {
+ removePreference(KEY_REMOVE_USER);
+ }
+ mPhonePref.setOnPreferenceChangeListener(this);
}
@Override
public boolean onPreferenceClick(Preference preference) {
if (preference == mRemoveUserPref) {
- if (canDeleteUser()) {
- showDialog(DIALOG_CONFIRM_REMOVE);
+ if (!mUserManager.isAdminUser()) {
+ throw new RuntimeException("Only admins can remove a user");
}
- return true;
- } else if (preference == mSwitchUserPref) {
- if (canSwitchUserNow()) {
- switchUser();
- }
+ showDialog(DIALOG_CONFIRM_REMOVE);
return true;
}
return false;
@@ -116,7 +126,7 @@
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (Boolean.TRUE.equals(newValue)) {
- showDialog(mUserInfo.isGuest() ? DIALOG_CONFIRM_ENABLE_CALLING
+ showDialog(mGuestUser ? DIALOG_CONFIRM_ENABLE_CALLING
: DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS);
return false;
}
@@ -124,135 +134,9 @@
return true;
}
- @Override
- public int getDialogMetricsCategory(int dialogId) {
- switch (dialogId) {
- case DIALOG_CONFIRM_REMOVE:
- return SettingsEnums.DIALOG_USER_REMOVE;
- case DIALOG_CONFIRM_ENABLE_CALLING:
- return SettingsEnums.DIALOG_USER_ENABLE_CALLING;
- case DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS:
- return SettingsEnums.DIALOG_USER_ENABLE_CALLING_AND_SMS;
- default:
- return 0;
- }
- }
-
- @Override
- public Dialog onCreateDialog(int dialogId) {
- Context context = getActivity();
- if (context == null) {
- return null;
- }
- switch (dialogId) {
- case DIALOG_CONFIRM_REMOVE:
- return UserDialogs.createRemoveDialog(getActivity(), mUserInfo.id,
- (dialog, which) -> removeUser());
- case DIALOG_CONFIRM_ENABLE_CALLING:
- return UserDialogs.createEnablePhoneCallsDialog(getActivity(),
- (dialog, which) -> enableCallsAndSms(true));
- case DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS:
- return UserDialogs.createEnablePhoneCallsAndSmsDialog(getActivity(),
- (dialog, which) -> enableCallsAndSms(true));
- }
- throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
- }
-
- @VisibleForTesting
- @Override
- protected void showDialog(int dialogId) {
- super.showDialog(dialogId);
- }
-
- @VisibleForTesting
- void initialize(Context context, Bundle arguments) {
- int userId = arguments != null ? arguments.getInt(EXTRA_USER_ID, USER_NULL) : USER_NULL;
- if (userId == USER_NULL) {
- throw new IllegalStateException("Arguments to this fragment must contain the user id");
- }
- mUserInfo = mUserManager.getUserInfo(userId);
-
- mSwitchUserPref = findPreference(KEY_SWITCH_USER);
- mPhonePref = findPreference(KEY_ENABLE_TELEPHONY);
- mRemoveUserPref = findPreference(KEY_REMOVE_USER);
-
- mSwitchUserPref.setTitle(
- context.getString(com.android.settingslib.R.string.user_switch_to_user,
- mUserInfo.name));
- mSwitchUserPref.setOnPreferenceClickListener(this);
-
- if (!mUserManager.isAdminUser()) { // non admin users can't remove users and allow calls
- removePreference(KEY_ENABLE_TELEPHONY);
- removePreference(KEY_REMOVE_USER);
- } else {
- if (!Utils.isVoiceCapable(context)) { // no telephony
- removePreference(KEY_ENABLE_TELEPHONY);
- }
-
- if (!mUserInfo.isGuest()) {
- mPhonePref.setChecked(!mUserManager.hasUserRestriction(
- UserManager.DISALLOW_OUTGOING_CALLS, new UserHandle(userId)));
- mRemoveUserPref.setTitle(R.string.user_remove_user);
- } else {
- // These are not for an existing user, just general Guest settings.
- // Default title is for calling and SMS. Change to calling-only here
- mPhonePref.setTitle(R.string.user_enable_calling);
- mDefaultGuestRestrictions = mUserManager.getDefaultGuestRestrictions();
- mPhonePref.setChecked(
- !mDefaultGuestRestrictions.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
- mRemoveUserPref.setTitle(R.string.user_exit_guest_title);
- }
- if (RestrictedLockUtilsInternal.hasBaseUserRestriction(context,
- UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId())) {
- removePreference(KEY_REMOVE_USER);
- }
-
- mRemoveUserPref.setOnPreferenceClickListener(this);
- mPhonePref.setOnPreferenceChangeListener(this);
- }
- }
-
- @VisibleForTesting
- boolean canDeleteUser() {
- if (!mUserManager.isAdminUser()) {
- return false;
- }
-
- Context context = getActivity();
- if (context == null) {
- return false;
- }
-
- final RestrictedLockUtils.EnforcedAdmin removeDisallowedAdmin =
- RestrictedLockUtilsInternal.checkIfRestrictionEnforced(context,
- UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId());
- if (removeDisallowedAdmin != null) {
- RestrictedLockUtils.sendShowAdminSupportDetailsIntent(context,
- removeDisallowedAdmin);
- return false;
- }
- return true;
- }
-
- @VisibleForTesting
- boolean canSwitchUserNow() {
- return mUserManager.getUserSwitchability() == UserManager.SWITCHABILITY_STATUS_OK;
- }
-
- @VisibleForTesting
- void switchUser() {
- try {
- ActivityManager.getService().switchUser(mUserInfo.id);
- } catch (RemoteException re) {
- Log.e(TAG, "Error while switching to other user.");
- } finally {
- finishFragment();
- }
- }
-
- private void enableCallsAndSms(boolean enabled) {
+ void enableCallsAndSms(boolean enabled) {
mPhonePref.setChecked(enabled);
- if (mUserInfo.isGuest()) {
+ if (mGuestUser) {
mDefaultGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, !enabled);
// SMS is always disabled for guest
mDefaultGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true);
@@ -262,7 +146,7 @@
// TODO: Maybe setDefaultGuestRestrictions() can internally just set the restrictions
// on any existing guest rather than do it here with multiple Binder calls.
List<UserInfo> users = mUserManager.getUsers(true);
- for (UserInfo user : users) {
+ for (UserInfo user: users) {
if (user.isGuest()) {
UserHandle userHandle = UserHandle.of(user.id);
for (String key : mDefaultGuestRestrictions.keySet()) {
@@ -279,7 +163,51 @@
}
}
- private void removeUser() {
+ @Override
+ public Dialog onCreateDialog(int dialogId) {
+ Context context = getActivity();
+ if (context == null) return null;
+ switch (dialogId) {
+ case DIALOG_CONFIRM_REMOVE:
+ return UserDialogs.createRemoveDialog(getActivity(), mUserInfo.id,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ removeUser();
+ }
+ });
+ case DIALOG_CONFIRM_ENABLE_CALLING:
+ return UserDialogs.createEnablePhoneCallsDialog(getActivity(),
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ enableCallsAndSms(true);
+ }
+ });
+ case DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS:
+ return UserDialogs.createEnablePhoneCallsAndSmsDialog(getActivity(),
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ enableCallsAndSms(true);
+ }
+ });
+ }
+ throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
+ }
+
+ @Override
+ public int getDialogMetricsCategory(int dialogId) {
+ switch (dialogId) {
+ case DIALOG_CONFIRM_REMOVE:
+ return SettingsEnums.DIALOG_USER_REMOVE;
+ case DIALOG_CONFIRM_ENABLE_CALLING:
+ return SettingsEnums.DIALOG_USER_ENABLE_CALLING;
+ case DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS:
+ return SettingsEnums.DIALOG_USER_ENABLE_CALLING_AND_SMS;
+ default:
+ return 0;
+ }
+ }
+
+ void removeUser() {
mUserManager.removeUser(mUserInfo.id);
finishFragment();
}
diff --git a/src/com/android/settings/users/UserPreference.java b/src/com/android/settings/users/UserPreference.java
index 0b78d78..3603d44 100644
--- a/src/com/android/settings/users/UserPreference.java
+++ b/src/com/android/settings/users/UserPreference.java
@@ -21,16 +21,18 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.util.AttributeSet;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ImageView;
import androidx.preference.PreferenceViewHolder;
+import com.android.settings.R;
+import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.RestrictedPreference;
import java.util.Comparator;
-/**
- * Preference for a user that appear on {@link UserSettings} screen.
- */
public class UserPreference extends RestrictedPreference {
private static final int ALPHA_ENABLED = 255;
private static final int ALPHA_DISABLED = 102;
@@ -42,7 +44,8 @@
if (p1 == null) {
return -1;
- } else if (p2 == null) {
+ }
+ else if (p2 == null) {
return 1;
}
int sn1 = p1.getSerialNumber();
@@ -55,15 +58,26 @@
return 0;
};
+ private OnClickListener mDeleteClickListener;
+ private OnClickListener mSettingsClickListener;
private int mSerialNumber = -1;
private int mUserId = USERID_UNKNOWN;
+ static final int SETTINGS_ID = R.id.manage_user;
+ static final int DELETE_ID = R.id.trash_user;
public UserPreference(Context context, AttributeSet attrs) {
- this(context, attrs, USERID_UNKNOWN);
+ this(context, attrs, USERID_UNKNOWN, null, null);
}
- UserPreference(Context context, AttributeSet attrs, int userId) {
+ UserPreference(Context context, AttributeSet attrs, int userId,
+ OnClickListener settingsListener,
+ OnClickListener deleteListener) {
super(context, attrs);
+ if (deleteListener != null || settingsListener != null) {
+ setWidgetLayoutResource(R.layout.restricted_preference_user_delete_widget);
+ }
+ mDeleteClickListener = deleteListener;
+ mSettingsClickListener = settingsListener;
mUserId = userId;
useAdminDisabledSummary(true);
}
@@ -78,13 +92,62 @@
@Override
protected boolean shouldHideSecondTarget() {
- return true;
+ if (isDisabledByAdmin()) {
+ // Disabled by admin, show no secondary target.
+ return true;
+ }
+ if (canDeleteUser()) {
+ // Need to show delete user target so don't hide.
+ return false;
+ }
+ // Hide if don't have advanced setting listener.
+ return mSettingsClickListener == null;
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
- dimIcon(isDisabledByAdmin());
+ final boolean disabledByAdmin = isDisabledByAdmin();
+ dimIcon(disabledByAdmin);
+ View userDeleteWidget = view.findViewById(R.id.user_delete_widget);
+ if (userDeleteWidget != null) {
+ userDeleteWidget.setVisibility(disabledByAdmin ? View.GONE : View.VISIBLE);
+ }
+ if (!disabledByAdmin) {
+ View deleteDividerView = view.findViewById(R.id.divider_delete);
+ View manageDividerView = view.findViewById(R.id.divider_manage);
+ View deleteView = view.findViewById(R.id.trash_user);
+ if (deleteView != null) {
+ if (canDeleteUser()) {
+ deleteView.setVisibility(View.VISIBLE);
+ deleteDividerView.setVisibility(View.VISIBLE);
+ deleteView.setOnClickListener(mDeleteClickListener);
+ deleteView.setTag(this);
+ } else {
+ deleteView.setVisibility(View.GONE);
+ deleteDividerView.setVisibility(View.GONE);
+ }
+ }
+ ImageView manageView = (ImageView) view.findViewById(R.id.manage_user);
+ if (manageView != null) {
+ if (mSettingsClickListener != null) {
+ manageView.setVisibility(View.VISIBLE);
+ manageDividerView.setVisibility(mDeleteClickListener == null
+ ? View.VISIBLE : View.GONE);
+ manageView.setOnClickListener(mSettingsClickListener);
+ manageView.setTag(this);
+ } else {
+ manageView.setVisibility(View.GONE);
+ manageDividerView.setVisibility(View.GONE);
+ }
+ }
+ }
+ }
+
+ private boolean canDeleteUser() {
+ return mDeleteClickListener != null
+ && !RestrictedLockUtilsInternal.hasBaseUserRestriction(getContext(),
+ UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId());
}
private int getSerialNumber() {
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 7d4ab5d..38ef199 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -48,6 +48,7 @@
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import android.view.View;
import android.widget.SimpleAdapter;
import androidx.annotation.VisibleForTesting;
@@ -68,6 +69,7 @@
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.widget.SwitchBar;
import com.android.settings.widget.SwitchBarController;
+import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.RestrictedPreference;
@@ -87,14 +89,15 @@
/**
* Screen that manages the list of users on the device.
- * Secondary users and a guest user can be created if there is no restriction.
+ * Guest user is an always visible entry, even if the guest is not currently
+ * active/created. It is meant for controlling properties of a guest user.
*
- * The first user in the list is always the current user.
+ * The first one is always the current user.
* Owner is the primary user.
*/
@SearchIndexable
public class UserSettings extends SettingsPreferenceFragment
- implements Preference.OnPreferenceClickListener,
+ implements Preference.OnPreferenceClickListener, View.OnClickListener,
MultiUserSwitchBarController.OnMultiUserSwitchChangedListener,
DialogInterface.OnDismissListener {
@@ -108,7 +111,6 @@
private static final String KEY_USER_LIST = "user_list";
private static final String KEY_USER_ME = "user_me";
private static final String KEY_USER_GUEST = "user_guest";
- private static final String KEY_ADD_GUEST = "guest_add";
private static final String KEY_ADD_USER = "user_add";
private static final String KEY_ADD_USER_WHEN_LOCKED = "user_settings_add_users_when_locked";
private static final String KEY_MULTIUSER_FOOTER = "multiuser_footer";
@@ -154,11 +156,7 @@
@VisibleForTesting
UserPreference mMePreference;
@VisibleForTesting
- RestrictedPreference mAddGuest;
- @VisibleForTesting
RestrictedPreference mAddUser;
- @VisibleForTesting
- SparseArray<Bitmap> mUserIcons = new SparseArray<>();
private int mRemovingUserId = -1;
private int mAddedUserId = 0;
private boolean mAddingUser;
@@ -167,6 +165,7 @@
private boolean mShouldUpdateUserList = true;
private final Object mUserLock = new Object();
private UserManager mUserManager;
+ private SparseArray<Bitmap> mUserIcons = new SparseArray<>();
private static SparseArray<Bitmap> sDarkDefaultUserBitmapCache = new SparseArray<>();
private MultiUserSwitchBarController mSwitchBarController;
@@ -272,17 +271,15 @@
final int myUserId = UserHandle.myUserId();
mUserListCategory = (PreferenceGroup) findPreference(KEY_USER_LIST);
- mMePreference = new UserPreference(getPrefContext(), null /* attrs */, myUserId);
+ mMePreference = new UserPreference(getPrefContext(), null /* attrs */, myUserId,
+ null /* settings icon handler */,
+ null /* delete icon handler */);
mMePreference.setKey(KEY_USER_ME);
mMePreference.setOnPreferenceClickListener(this);
if (mUserCaps.mIsAdmin) {
mMePreference.setSummary(R.string.user_admin);
}
-
- mAddGuest = findPreference(KEY_ADD_GUEST);
- mAddGuest.setOnPreferenceClickListener(this);
-
- mAddUser = findPreference(KEY_ADD_USER);
+ mAddUser = (RestrictedPreference) findPreference(KEY_ADD_USER);
if (!mUserCaps.mCanAddRestrictedProfile) {
// Label should only mention adding a "user", not a "profile"
mAddUser.setTitle(R.string.user_add_user_menu);
@@ -347,7 +344,8 @@
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
int pos = 0;
- if (!mUserCaps.mIsAdmin && canSwitchUserNow()) {
+ final boolean canSwitchUsers = mUserManager.canSwitchUsers();
+ if (!mUserCaps.mIsAdmin && canSwitchUsers) {
String nickname = mUserManager.getUserName();
MenuItem removeThisUser = menu.add(0, MENU_REMOVE_USER, pos++,
getResources().getString(R.string.user_remove_user_menu, nickname));
@@ -388,13 +386,10 @@
* Loads profile information for the current user.
*/
private void loadProfile() {
- if (isCurrentUserGuest()) {
+ if (mUserCaps.mIsGuest) {
// No need to load profile information
mMePreference.setIcon(getEncircledDefaultIcon());
mMePreference.setTitle(R.string.user_exit_guest_title);
- mMePreference.setSelectable(true);
- // removing a guest will result in switching back to the admin user
- mMePreference.setEnabled(canSwitchUserNow());
return;
}
@@ -417,9 +412,7 @@
}
private void finishLoadProfile(String profileName) {
- if (getActivity() == null) {
- return;
- }
+ if (getActivity() == null) return;
mMePreference.setTitle(getString(R.string.user_you, profileName));
int myUserId = UserHandle.myUserId();
Bitmap b = mUserManager.getUserIcon(myUserId);
@@ -484,28 +477,38 @@
private void onManageUserClicked(int userId, boolean newUser) {
mAddingUser = false;
- UserInfo userInfo = mUserManager.getUserInfo(userId);
- if (userInfo.isRestricted() && mUserCaps.mIsAdmin) {
+ if (userId == UserPreference.USERID_GUEST_DEFAULTS) {
+ Bundle extras = new Bundle();
+ extras.putBoolean(UserDetailsSettings.EXTRA_USER_GUEST, true);
+ new SubSettingLauncher(getContext())
+ .setDestination(UserDetailsSettings.class.getName())
+ .setArguments(extras)
+ .setTitleRes(R.string.user_guest)
+ .setSourceMetricsCategory(getMetricsCategory())
+ .launch();
+ return;
+ }
+ UserInfo info = mUserManager.getUserInfo(userId);
+ if (info.isRestricted() && mUserCaps.mIsAdmin) {
Bundle extras = new Bundle();
extras.putInt(RestrictedProfileSettings.EXTRA_USER_ID, userId);
extras.putBoolean(RestrictedProfileSettings.EXTRA_NEW_USER, newUser);
- extras.putBoolean(RestrictedProfileSettings.EXTRA_SHOW_SWITCH_USER, canSwitchUserNow());
new SubSettingLauncher(getContext())
.setDestination(RestrictedProfileSettings.class.getName())
.setArguments(extras)
.setTitleRes(R.string.user_restrictions_title)
.setSourceMetricsCategory(getMetricsCategory())
.launch();
- } else if (userId == UserHandle.myUserId()) {
+ } else if (info.id == UserHandle.myUserId()) {
// Jump to owner info panel
OwnerInfoSettings.show(this);
- } else {
- Bundle extras = new Bundle();
+ } else if (mUserCaps.mIsAdmin) {
+ final Bundle extras = new Bundle();
extras.putInt(UserDetailsSettings.EXTRA_USER_ID, userId);
new SubSettingLauncher(getContext())
.setDestination(UserDetailsSettings.class.getName())
.setArguments(extras)
- .setTitleText(userInfo.name)
+ .setTitleText(info.name)
.setSourceMetricsCategory(getMetricsCategory())
.launch();
}
@@ -535,9 +538,7 @@
@Override
public Dialog onCreateDialog(int dialogId) {
Context context = getActivity();
- if (context == null) {
- return null;
- }
+ if (context == null) return null;
switch (dialogId) {
case DIALOG_CONFIRM_REMOVE: {
Dialog dlg =
@@ -810,7 +811,7 @@
}
private void removeThisUser() {
- if (!canSwitchUserNow()) {
+ if (!mUserManager.canSwitchUsers()) {
Log.w(TAG, "Cannot remove current user when switching is disabled");
return;
}
@@ -881,14 +882,10 @@
}
private void switchUserNow(int userId) {
- if (!canSwitchUserNow()) {
- return;
- }
-
try {
ActivityManager.getService().switchUser(userId);
} catch (RemoteException re) {
- Log.e(TAG, "Error while switching to other user.");
+ // Nothing to do
}
}
@@ -897,7 +894,7 @@
*/
private void exitGuest() {
// Just to be safe
- if (!isCurrentUserGuest()) {
+ if (!mUserCaps.mIsGuest) {
return;
}
removeThisUser();
@@ -911,12 +908,12 @@
}
final List<UserInfo> users = mUserManager.getUsers(true);
+ final boolean voiceCapable = Utils.isVoiceCapable(context);
final ArrayList<Integer> missingIcons = new ArrayList<>();
final ArrayList<UserPreference> userPreferences = new ArrayList<>();
+ int guestId = UserPreference.USERID_GUEST_DEFAULTS;
userPreferences.add(mMePreference);
- boolean canOpenUserDetails =
- mUserCaps.mIsAdmin || (canSwitchUserNow() && !mUserCaps.mDisallowSwitchUser);
for (UserInfo user : users) {
if (!user.supportsSwitchToByUser()) {
// Only users that can be switched to should show up here.
@@ -927,38 +924,37 @@
if (user.id == UserHandle.myUserId()) {
pref = mMePreference;
} else if (user.isGuest()) {
- pref = new UserPreference(getPrefContext(), null, user.id);
- pref.setTitle(R.string.user_guest);
- pref.setIcon(getEncircledDefaultIcon());
- pref.setKey(KEY_USER_GUEST);
- userPreferences.add(pref);
- pref.setEnabled(canOpenUserDetails);
- pref.setSelectable(true);
-
- if (mUserCaps.mDisallowSwitchUser) {
- pref.setDisabledByAdmin(RestrictedLockUtilsInternal.getDeviceOwner(context));
- } else {
- pref.setDisabledByAdmin(null);
- }
- pref.setOnPreferenceClickListener(this);
+ // Skip over Guest. We add generic Guest settings after this loop
+ guestId = user.id;
+ continue;
} else {
- pref = new UserPreference(getPrefContext(), null, user.id);
+ // With Telephony:
+ // Secondary user: Settings
+ // Guest: Settings
+ // Restricted Profile: There is no Restricted Profile
+ // Without Telephony:
+ // Secondary user: Delete
+ // Guest: Nothing
+ // Restricted Profile: Settings
+ final boolean showSettings = mUserCaps.mIsAdmin
+ && (voiceCapable || user.isRestricted());
+ final boolean showDelete = mUserCaps.mIsAdmin
+ && (!voiceCapable && !user.isRestricted() && !user.isGuest());
+ pref = new UserPreference(getPrefContext(), null, user.id,
+ showSettings ? this : null,
+ showDelete ? this : null);
pref.setKey("id=" + user.id);
userPreferences.add(pref);
if (user.isAdmin()) {
pref.setSummary(R.string.user_admin);
}
pref.setTitle(user.name);
- pref.setOnPreferenceClickListener(this);
- pref.setEnabled(canOpenUserDetails);
- pref.setSelectable(true);
+ pref.setSelectable(false);
}
if (pref == null) {
continue;
}
- if (user.id != UserHandle.myUserId() && !user.isGuest() && !user.isInitialized()) {
- // sometimes after creating a guest the initialized flag isn't immediately set
- // and we don't want to show "Not set up" summary for them
+ if (!isInitialized(user)) {
if (user.isRestricted()) {
pref.setSummary(R.string.user_summary_restricted_not_set_up);
} else {
@@ -966,7 +962,10 @@
}
// Disallow setting up user which results in user switching when the restriction is
// set.
- pref.setEnabled(!mUserCaps.mDisallowSwitchUser && canSwitchUserNow());
+ if (!mUserCaps.mDisallowSwitchUser) {
+ pref.setOnPreferenceClickListener(this);
+ pref.setSelectable(mUserManager.canSwitchUsers());
+ }
} else if (user.isRestricted()) {
pref.setSummary(R.string.user_summary_restricted_profile);
}
@@ -987,13 +986,53 @@
// Add a temporary entry for the user being created
if (mAddingUser) {
UserPreference pref = new UserPreference(getPrefContext(), null,
- UserPreference.USERID_UNKNOWN);
+ UserPreference.USERID_UNKNOWN, null, null);
pref.setEnabled(false);
pref.setTitle(mAddingUserName);
pref.setIcon(getEncircledDefaultIcon());
userPreferences.add(pref);
}
+ // Check if Guest tile should be added.
+ if (!mUserCaps.mIsGuest && (mUserCaps.mCanAddGuest ||
+ mUserCaps.mDisallowAddUserSetByAdmin)) {
+ // Add a virtual Guest user for guest defaults
+ UserPreference pref = new UserPreference(getPrefContext(), null,
+ UserPreference.USERID_GUEST_DEFAULTS,
+ mUserCaps.mIsAdmin && voiceCapable ? this : null /* settings icon handler */,
+ null /* delete icon handler */);
+ pref.setTitle(R.string.user_guest);
+ pref.setIcon(getEncircledDefaultIcon());
+ pref.setKey(KEY_USER_GUEST);
+ userPreferences.add(pref);
+ if (mUserCaps.mDisallowAddUser) {
+ pref.setDisabledByAdmin(mUserCaps.mEnforcedAdmin);
+ } else if (mUserCaps.mDisallowSwitchUser) {
+ pref.setDisabledByAdmin(RestrictedLockUtilsInternal.getDeviceOwner(context));
+ } else {
+ pref.setDisabledByAdmin(null);
+ }
+ if (!mUserManager.canSwitchUsers()) {
+ pref.setSelectable(false);
+ }
+ int finalGuestId = guestId;
+ pref.setOnPreferenceClickListener(preference -> {
+ int id = finalGuestId;
+ if (id == UserPreference.USERID_GUEST_DEFAULTS) {
+ UserInfo guest = mUserManager.createGuest(
+ getContext(), preference.getTitle().toString());
+ if (guest != null) {
+ id = guest.id;
+ }
+ }
+ try {
+ ActivityManager.getService().switchUser(id);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ return true;
+ });
+ }
// Sort list of users by serialNum
Collections.sort(userPreferences, UserPreference.SERIAL_NUMBER_COMPARATOR);
@@ -1025,7 +1064,6 @@
mMultiUserFooterPreferenceController.updateState(multiUserFooterPrefence);
mUserListCategory.setVisible(mUserCaps.mUserSwitcherEnabled);
- updateAddGuest(context, users.stream().anyMatch(UserInfo::isGuest));
updateAddUser(context);
if (!mUserCaps.mUserSwitcherEnabled) {
@@ -1039,38 +1077,15 @@
}
- private boolean isCurrentUserGuest() {
- return mUserCaps.mIsGuest;
- }
-
- private boolean canSwitchUserNow() {
- return mUserManager.getUserSwitchability() == UserManager.SWITCHABILITY_STATUS_OK;
- }
-
- private void updateAddGuest(Context context, boolean isGuestAlreadyCreated) {
- if (!isGuestAlreadyCreated && mUserCaps.mCanAddGuest
- && WizardManagerHelper.isDeviceProvisioned(context)
- && mUserCaps.mUserSwitcherEnabled) {
- mAddGuest.setVisible(true);
- mAddGuest.setIcon(getEncircledDefaultIcon());
- mAddGuest.setEnabled(canSwitchUserNow());
- mAddGuest.setSelectable(true);
- } else {
- mAddGuest.setVisible(false);
- }
- }
-
private void updateAddUser(Context context) {
if ((mUserCaps.mCanAddUser || mUserCaps.mDisallowAddUserSetByAdmin)
&& WizardManagerHelper.isDeviceProvisioned(context)
&& mUserCaps.mUserSwitcherEnabled) {
mAddUser.setVisible(true);
- mAddUser.setSelectable(true);
- final boolean canAddMoreUsers = mUserManager.canAddMoreUsers();
- mAddUser.setEnabled(canAddMoreUsers && !mAddingUser && canSwitchUserNow());
- if (!canAddMoreUsers) {
- mAddUser.setSummary(
- getString(R.string.user_add_max_count, getRealUsersCount()));
+ final boolean moreUsers = mUserManager.canAddMoreUsers();
+ mAddUser.setEnabled(moreUsers && !mAddingUser && mUserManager.canSwitchUsers());
+ if (!moreUsers) {
+ mAddUser.setSummary(getString(R.string.user_add_max_count, getMaxRealUsers()));
} else {
mAddUser.setSummary(null);
}
@@ -1083,15 +1098,18 @@
}
}
- /**
- * @return number of non-guest non-managed users
- */
- @VisibleForTesting
- int getRealUsersCount() {
- return (int) mUserManager.getUsers()
- .stream()
- .filter(user -> !user.isGuest() && !user.isProfile())
- .count();
+ private int getMaxRealUsers() {
+ // guest is not counted against getMaxSupportedUsers() number
+ final int maxUsersAndGuest = UserManager.getMaxSupportedUsers() + 1;
+ final List<UserInfo> users = mUserManager.getUsers();
+ // managed profiles are counted against getMaxSupportedUsers()
+ int managedProfiles = 0;
+ for (UserInfo user : users) {
+ if (user.isManagedProfile()) {
+ managedProfiles++;
+ }
+ }
+ return maxUsersAndGuest - managedProfiles;
}
private void loadIconsAsync(List<Integer> missingIcons) {
@@ -1133,12 +1151,12 @@
@Override
public boolean onPreferenceClick(Preference pref) {
if (pref == mMePreference) {
- if (isCurrentUserGuest()) {
+ if (mUserCaps.mIsGuest) {
showDialog(DIALOG_CONFIRM_EXIT_GUEST);
return true;
}
// If this is a limited user, launch the user info settings instead of profile editor
- if (mUserManager.isRestrictedProfile()) {
+ if (mUserManager.isLinkedUser()) {
onManageUserClicked(UserHandle.myUserId(), false);
} else {
showDialog(DIALOG_USER_PROFILE_EDITOR);
@@ -1147,11 +1165,9 @@
int userId = ((UserPreference) pref).getUserId();
// Get the latest status of the user
UserInfo user = mUserManager.getUserInfo(userId);
- if (!user.isInitialized()) {
+ if (!isInitialized(user)) {
mHandler.sendMessage(mHandler.obtainMessage(
MESSAGE_SETUP_USER, user.id, user.serialNumber));
- } else {
- onManageUserClicked(userId, false);
}
} else if (pref == mAddUser) {
// If we allow both types, show a picker, otherwise directly go to
@@ -1161,20 +1177,40 @@
} else {
onAddUserClicked(USER_TYPE_USER);
}
- } else if (pref == mAddGuest) {
- UserInfo guest = mUserManager.createGuest(
- getContext(), getString(com.android.settingslib.R.string.user_guest));
- switchUserNow(guest.id);
}
return false;
}
+ private boolean isInitialized(UserInfo user) {
+ return (user.flags & UserInfo.FLAG_INITIALIZED) != 0;
+ }
+
private Drawable encircle(Bitmap icon) {
Drawable circled = CircleFramedDrawable.getInstance(getActivity(), icon);
return circled;
}
@Override
+ public void onClick(View v) {
+ if (v.getTag() instanceof UserPreference) {
+ int userId = ((UserPreference) v.getTag()).getUserId();
+ if (v.getId() == UserPreference.DELETE_ID) {
+ final EnforcedAdmin removeDisallowedAdmin =
+ RestrictedLockUtilsInternal.checkIfRestrictionEnforced(getContext(),
+ UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId());
+ if (removeDisallowedAdmin != null) {
+ RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(),
+ removeDisallowedAdmin);
+ } else {
+ onRemoveUserClicked(userId);
+ }
+ } else if (v.getId() == UserPreference.SETTINGS_ID) {
+ onManageUserClicked(userId, false);
+ }
+ }
+ }
+
+ @Override
public void onDismiss(DialogInterface dialog) {
synchronized (mUserLock) {
mRemovingUserId = -1;
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
index 673c0fe..659c5de 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
@@ -18,7 +18,6 @@
import android.annotation.UserIdInt;
import android.content.pm.UserInfo;
-import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManager.EnforcingUser;
@@ -44,18 +43,13 @@
private static boolean sIsSupportsMultipleUsers;
- private final List<String> mBaseRestrictions = new ArrayList<>();
- private final List<String> mUserRestrictions = new ArrayList<>();
- private final List<String> mGuestRestrictions = new ArrayList<>();
+ private final List<String> mRestrictions = new ArrayList<>();
private final Map<String, List<EnforcingUser>> mRestrictionSources = new HashMap<>();
private final List<UserInfo> mUserProfileInfos = new ArrayList<>();
private final Set<Integer> mManagedProfiles = new HashSet<>();
private boolean mIsQuietModeEnabled = false;
private int[] profileIdsForUser = new int[0];
private boolean mUserSwitchEnabled;
-
- private @UserManager.UserSwitchabilityResult int mSwitchabilityStatus =
- UserManager.SWITCHABILITY_STATUS_OK;
private final Map<Integer, Integer> mSameProfileGroupIds = Maps.newHashMap();
public void addProfile(UserInfo userInfo) {
@@ -88,32 +82,11 @@
@Implementation
protected boolean hasBaseUserRestriction(String restrictionKey, UserHandle userHandle) {
- return mBaseRestrictions.contains(restrictionKey);
+ return mRestrictions.contains(restrictionKey);
}
public void addBaseUserRestriction(String restriction) {
- mBaseRestrictions.add(restriction);
- }
-
- @Implementation
- protected boolean hasUserRestriction(@UserManager.UserRestrictionKey String restrictionKey,
- UserHandle userHandle) {
- return mUserRestrictions.contains(restrictionKey);
- }
-
- public void addUserRestriction(String restriction) {
- mUserRestrictions.add(restriction);
- }
-
- @Implementation
- protected Bundle getDefaultGuestRestrictions() {
- Bundle bundle = new Bundle();
- mGuestRestrictions.forEach(restriction -> bundle.putBoolean(restriction, true));
- return bundle;
- }
-
- public void addGuestUserRestriction(String restriction) {
- mGuestRestrictions.add(restriction);
+ mRestrictions.add(restriction);
}
public static ShadowUserManager getShadow() {
@@ -193,21 +166,4 @@
public void setSupportsMultipleUsers(boolean supports) {
sIsSupportsMultipleUsers = supports;
}
-
- @Implementation
- protected UserInfo getUserInfo(@UserIdInt int userId) {
- return mUserProfileInfos.stream()
- .filter(userInfo -> userInfo.id == userId)
- .findFirst()
- .orElse(super.getUserInfo(userId));
- }
-
- @Implementation
- protected @UserManager.UserSwitchabilityResult int getUserSwitchability() {
- return mSwitchabilityStatus;
- }
-
- public void setSwitchabilityStatus(@UserManager.UserSwitchabilityResult int newStatus) {
- mSwitchabilityStatus = newStatus;
- }
}
diff --git a/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java b/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java
deleted file mode 100644
index c51b2fc..0000000
--- a/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * Copyright (C) 2020 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.settings.users;
-
-import static android.os.UserManager.SWITCHABILITY_STATUS_OK;
-import static android.os.UserManager.SWITCHABILITY_STATUS_USER_IN_CALL;
-import static android.os.UserManager.SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.UserInfo;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.telephony.TelephonyManager;
-
-import androidx.fragment.app.FragmentActivity;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
-
-import com.android.settings.R;
-import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
-import com.android.settings.testutils.shadow.ShadowUserManager;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.android.controller.ActivityController;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadow.api.Shadow;
-import org.robolectric.util.ReflectionHelpers;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(RobolectricTestRunner.class)
-@Config(shadows = {
- ShadowUserManager.class,
- ShadowDevicePolicyManager.class
-})
-public class UserDetailsSettingsTest {
-
- private static final String KEY_SWITCH_USER = "switch_user";
- private static final String KEY_ENABLE_TELEPHONY = "enable_calling";
- private static final String KEY_REMOVE_USER = "remove_user";
-
- private static final int DIALOG_CONFIRM_REMOVE = 1;
-
- @Mock
- private TelephonyManager mTelephonyManager;
-
- private ShadowUserManager mUserManager;
-
- @Mock
- private Preference mSwitchUserPref;
- @Mock
- private SwitchPreference mPhonePref;
- @Mock
- private Preference mRemoveUserPref;
-
- private FragmentActivity mActivity;
- private Context mContext;
- private UserDetailsSettings mFragment;
- private Bundle mArguments;
- private UserInfo mUserInfo;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
-
- mActivity = spy(ActivityController.of(new FragmentActivity()).get());
- mContext = spy(RuntimeEnvironment.application);
- mFragment = spy(new UserDetailsSettings());
- mArguments = new Bundle();
-
- UserManager userManager = (UserManager) mContext.getSystemService(
- Context.USER_SERVICE);
- mUserManager = Shadow.extract(userManager);
-
- doReturn(mTelephonyManager).when(mActivity).getSystemService(Context.TELEPHONY_SERVICE);
-
- ReflectionHelpers.setField(mFragment, "mUserManager", userManager);
- doReturn(mActivity).when(mFragment).getActivity();
- doReturn(mContext).when(mFragment).getContext();
-
- doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
- doReturn("").when(mActivity).getString(anyInt(), anyString());
-
- doReturn(mSwitchUserPref).when(mFragment).findPreference(KEY_SWITCH_USER);
- doReturn(mPhonePref).when(mFragment).findPreference(KEY_ENABLE_TELEPHONY);
- doReturn(mRemoveUserPref).when(mFragment).findPreference(KEY_REMOVE_USER);
- }
-
- @After
- public void tearDown() {
- ShadowUserManager.reset();
- }
-
- @Test(expected = IllegalStateException.class)
- public void initialize_nullArguments_shouldThrowException() {
- mFragment.initialize(mActivity, null);
- }
-
- @Test(expected = IllegalStateException.class)
- public void initialize_emptyArguments_shouldThrowException() {
- mFragment.initialize(mActivity, new Bundle());
- }
-
- @Test
- public void initialize_userSelected_shouldSetupSwitchPref() {
- setupSelectedUser();
- doReturn("Switch to " + mUserInfo.name)
- .when(mActivity).getString(anyInt(), anyString());
-
- mFragment.initialize(mActivity, mArguments);
-
- verify(mActivity).getString(com.android.settingslib.R.string.user_switch_to_user,
- mUserInfo.name);
- verify(mSwitchUserPref).setTitle("Switch to " + mUserInfo.name);
- verify(mSwitchUserPref).setOnPreferenceClickListener(mFragment);
- verify(mFragment, never()).removePreference(KEY_SWITCH_USER);
- }
-
- @Test
- public void initialize_guestSelected_shouldSetupSwitchPref() {
- setupSelectedGuest();
- doReturn("Switch to " + mUserInfo.name)
- .when(mActivity).getString(anyInt(), anyString());
-
- mFragment.initialize(mActivity, mArguments);
-
- verify(mActivity).getString(com.android.settingslib.R.string.user_switch_to_user,
- mUserInfo.name);
- verify(mSwitchUserPref).setTitle("Switch to " + mUserInfo.name);
- verify(mSwitchUserPref).setOnPreferenceClickListener(mFragment);
- verify(mFragment, never()).removePreference(KEY_SWITCH_USER);
- }
-
- @Test
- public void onResume_canSwitch_shouldEnableSwitchPref() {
- mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_OK);
- mFragment.mSwitchUserPref = mSwitchUserPref;
- mFragment.onAttach(mContext);
-
- mFragment.onResume();
-
- verify(mSwitchUserPref).setEnabled(true);
- }
-
- @Test
- public void onResume_userInCall_shouldDisableSwitchPref() {
- mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_USER_IN_CALL);
- mFragment.mSwitchUserPref = mSwitchUserPref;
- mFragment.onAttach(mContext);
-
- mFragment.onResume();
-
- verify(mSwitchUserPref).setEnabled(false);
- }
-
- @Test
- public void onResume_switchDisallowed_shouldDisableSwitchPref() {
- mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED);
- mFragment.mSwitchUserPref = mSwitchUserPref;
- mFragment.onAttach(mContext);
-
- mFragment.onResume();
-
- verify(mSwitchUserPref).setEnabled(false);
- }
-
- @Test
- public void onResume_systemUserLocked_shouldDisableSwitchPref() {
- mUserManager.setSwitchabilityStatus(UserManager.SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED);
- mFragment.mSwitchUserPref = mSwitchUserPref;
- mFragment.onAttach(mContext);
-
- mFragment.onResume();
-
- verify(mSwitchUserPref).setEnabled(false);
- }
-
- @Test
- public void initialize_adminWithTelephony_shouldShowPhonePreference() {
- setupSelectedUser();
- doReturn(true).when(mTelephonyManager).isVoiceCapable();
- mUserManager.setIsAdminUser(true);
-
- mFragment.initialize(mActivity, mArguments);
-
- verify(mFragment, never()).removePreference(KEY_ENABLE_TELEPHONY);
- verify(mPhonePref).setOnPreferenceChangeListener(mFragment);
- }
-
- @Test
- public void initialize_adminNoTelephony_shouldNotShowPhonePreference() {
- setupSelectedUser();
- doReturn(false).when(mTelephonyManager).isVoiceCapable();
- mUserManager.setIsAdminUser(true);
- doReturn(null).when(mActivity).getSystemService(Context.TELEPHONY_SERVICE);
-
- mFragment.initialize(mActivity, mArguments);
-
- verify(mFragment).removePreference(KEY_ENABLE_TELEPHONY);
- }
-
- @Test
- public void initialize_nonAdminWithTelephony_shouldNotShowPhonePreference() {
- setupSelectedUser();
- doReturn(true).when(mTelephonyManager).isVoiceCapable();
- mUserManager.setIsAdminUser(false);
-
- mFragment.initialize(mActivity, mArguments);
-
- verify(mFragment).removePreference(KEY_ENABLE_TELEPHONY);
- }
-
- @Test
- public void initialize_adminSelectsSecondaryUser_shouldShowRemovePreference() {
- setupSelectedUser();
- mUserManager.setIsAdminUser(true);
-
- mFragment.initialize(mActivity, mArguments);
-
- verify(mRemoveUserPref).setOnPreferenceClickListener(mFragment);
- verify(mRemoveUserPref).setTitle(R.string.user_remove_user);
- verify(mFragment, never()).removePreference(KEY_REMOVE_USER);
- }
-
- @Test
- public void initialize_adminSelectsGuest_shouldShowRemovePreference() {
- setupSelectedGuest();
- mUserManager.setIsAdminUser(true);
-
- mFragment.initialize(mActivity, mArguments);
-
- verify(mRemoveUserPref).setOnPreferenceClickListener(mFragment);
- verify(mRemoveUserPref).setTitle(R.string.user_exit_guest_title);
- verify(mFragment, never()).removePreference(KEY_REMOVE_USER);
- }
-
- @Test
- public void initialize_nonAdmin_shouldNotShowRemovePreference() {
- setupSelectedUser();
- mUserManager.setIsAdminUser(false);
-
- mFragment.initialize(mActivity, mArguments);
-
- verify(mFragment).removePreference(KEY_REMOVE_USER);
- }
-
- @Test
- public void initialize_disallowRemoveUserRestriction_shouldNotShowRemovePreference() {
- setupSelectedUser();
- mUserManager.setIsAdminUser(true);
- mUserManager.addBaseUserRestriction(UserManager.DISALLOW_REMOVE_USER);
-
- mFragment.initialize(mActivity, mArguments);
-
- verify(mFragment).removePreference(KEY_REMOVE_USER);
- }
-
- @Test
- public void initialize_userHasCallRestriction_shouldSetPhoneSwitchUnChecked() {
- setupSelectedUser();
- mUserManager.setIsAdminUser(true);
- mUserManager.addUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS);
-
- mFragment.initialize(mActivity, mArguments);
-
- verify(mPhonePref).setChecked(false);
- }
-
- @Test
- public void initialize_noCallRestriction_shouldSetPhoneSwitchChecked() {
- setupSelectedUser();
- mUserManager.setIsAdminUser(true);
-
- mFragment.initialize(mActivity, mArguments);
-
- verify(mPhonePref).setChecked(true);
- }
-
- @Test
- public void initialize_guestSelected_noCallRestriction_shouldSetPhonePreference() {
- setupSelectedGuest();
- mUserManager.setIsAdminUser(true);
-
- mFragment.initialize(mActivity, mArguments);
-
- verify(mPhonePref).setTitle(R.string.user_enable_calling);
- verify(mPhonePref).setChecked(true);
- }
-
- @Test
- public void initialize_guestSelected_callRestriction_shouldSetPhonePreference() {
- setupSelectedGuest();
- mUserManager.setIsAdminUser(true);
- mUserManager.addGuestUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS);
-
- mFragment.initialize(mActivity, mArguments);
-
- verify(mPhonePref).setTitle(R.string.user_enable_calling);
- verify(mPhonePref).setChecked(false);
- }
-
- @Test
- public void onPreferenceClick_switchClicked_canSwitch_shouldSwitch() {
- setupSelectedUser();
- mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_OK);
- mFragment.mSwitchUserPref = mSwitchUserPref;
- mFragment.mRemoveUserPref = mRemoveUserPref;
- mFragment.mUserInfo = mUserInfo;
-
- mFragment.onPreferenceClick(mSwitchUserPref);
-
- verify(mFragment).switchUser();
- }
-
- @Test
- public void onPreferenceClick_switchClicked_canNotSwitch_doNothing() {
- setupSelectedUser();
- mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED);
- mFragment.mSwitchUserPref = mSwitchUserPref;
- mFragment.mRemoveUserPref = mRemoveUserPref;
- mFragment.mUserInfo = mUserInfo;
-
- mFragment.onPreferenceClick(mSwitchUserPref);
-
- verify(mFragment, never()).switchUser();
- }
-
- @Test
- public void onPreferenceClick_removeClicked_canDelete_shouldShowDialog() {
- setupSelectedUser();
- mFragment.mUserInfo = mUserInfo;
- mUserManager.setIsAdminUser(true);
- mFragment.mSwitchUserPref = mSwitchUserPref;
- mFragment.mRemoveUserPref = mRemoveUserPref;
- doNothing().when(mFragment).showDialog(anyInt());
-
- mFragment.onPreferenceClick(mRemoveUserPref);
-
- verify(mFragment).canDeleteUser();
- verify(mFragment).showDialog(DIALOG_CONFIRM_REMOVE);
- }
-
- @Test
- public void onPreferenceClick_removeClicked_canNotDelete_doNothing() {
- setupSelectedUser();
- mFragment.mUserInfo = mUserInfo;
- mUserManager.setIsAdminUser(false);
- mFragment.mSwitchUserPref = mSwitchUserPref;
- mFragment.mRemoveUserPref = mRemoveUserPref;
- doNothing().when(mFragment).showDialog(anyInt());
-
- mFragment.onPreferenceClick(mRemoveUserPref);
-
- verify(mFragment).canDeleteUser();
- verify(mFragment, never()).showDialog(DIALOG_CONFIRM_REMOVE);
- }
-
- @Test
- public void onPreferenceClick_unknownPreferenceClicked_doNothing() {
- setupSelectedUser();
- mFragment.mUserInfo = mUserInfo;
- mFragment.mSwitchUserPref = mSwitchUserPref;
- mFragment.mRemoveUserPref = mRemoveUserPref;
-
- mFragment.onPreferenceClick(mock(UserPreference.class));
-
- verify(mFragment).onPreferenceClick(any());
- verifyNoMoreInteractions(mFragment);
- }
-
- @Test
- public void canDeleteUser_nonAdminUser_shouldReturnFalse() {
- mUserManager.setIsAdminUser(false);
-
- boolean result = mFragment.canDeleteUser();
-
- assertThat(result).isFalse();
- }
-
- @Test
- public void canDeleteUser_adminSelectsUser_noRestrictions_shouldReturnTrue() {
- setupSelectedUser();
- mUserManager.setIsAdminUser(true);
-
- boolean result = mFragment.canDeleteUser();
-
- assertThat(result).isTrue();
- }
-
- @Test
- public void canDeleteUser_adminSelectsUser_hasRemoveRestriction_shouldReturnFalse() {
- setupSelectedUser();
- mUserManager.setIsAdminUser(true);
- ComponentName componentName = new ComponentName("test", "test");
- ShadowDevicePolicyManager.getShadow().setDeviceOwnerComponentOnAnyUser(componentName);
- ShadowDevicePolicyManager.getShadow().setDeviceOwnerUserId(UserHandle.myUserId());
- List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>();
- enforcingUsers.add(new UserManager.EnforcingUser(UserHandle.myUserId(),
- UserManager.RESTRICTION_SOURCE_DEVICE_OWNER));
- mUserManager.setUserRestrictionSources(
- UserManager.DISALLOW_REMOVE_USER,
- UserHandle.of(UserHandle.myUserId()),
- enforcingUsers
- );
-
- boolean result = mFragment.canDeleteUser();
-
- assertThat(result).isFalse();
- }
-
- private void setupSelectedUser() {
- mArguments.putInt("user_id", 1);
- mUserInfo = new UserInfo(1, "Tom", null,
- UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED,
- UserManager.USER_TYPE_FULL_SECONDARY);
-
- mUserManager.addProfile(mUserInfo);
- }
-
- private void setupSelectedGuest() {
- mArguments.putInt("user_id", 23);
- mUserInfo = new UserInfo(23, "Guest", null,
- UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_GUEST,
- UserManager.USER_TYPE_FULL_GUEST);
-
- mUserManager.addProfile(mUserInfo);
- }
-}
diff --git a/tests/robotests/src/com/android/settings/users/UserPreferenceTest.java b/tests/robotests/src/com/android/settings/users/UserPreferenceTest.java
index 28f415e..345784a 100644
--- a/tests/robotests/src/com/android/settings/users/UserPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/users/UserPreferenceTest.java
@@ -18,8 +18,12 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
import android.content.Context;
import android.os.UserHandle;
+import android.view.View;
import com.android.settingslib.RestrictedPreferenceHelper;
@@ -44,12 +48,28 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
- mUserPreference = new UserPreference(mContext, null /* attrs */, UserHandle.USER_CURRENT);
+ mUserPreference = new UserPreference(mContext, null /* attrs */, UserHandle.USER_CURRENT,
+ null /* settingsListener */, null /* deleteListener */);
ReflectionHelpers.setField(mUserPreference, "mHelper", mRestrictedPreferenceHelper);
}
@Test
- public void testShouldHideSecondTarget_shouldHide() {
+ public void testShouldHideSecondTarget_noListener_shouldHide() {
assertThat(mUserPreference.shouldHideSecondTarget()).isTrue();
}
+
+ @Test
+ public void testShouldHideSecondTarget_disabledByAdmin_shouldHide() {
+ when(mRestrictedPreferenceHelper.isDisabledByAdmin()).thenReturn(true);
+
+ assertThat(mUserPreference.shouldHideSecondTarget()).isTrue();
+ }
+
+ @Test
+ public void testShouldHideSecondTarget_hasSettingListener_shouldNotHide() {
+ ReflectionHelpers.setField(mUserPreference, "mSettingsClickListener",
+ mock(View.OnClickListener.class));
+
+ assertThat(mUserPreference.shouldHideSecondTarget()).isFalse();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/users/UserSettingsTest.java b/tests/robotests/src/com/android/settings/users/UserSettingsTest.java
index d2a1840..5853308 100644
--- a/tests/robotests/src/com/android/settings/users/UserSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/users/UserSettingsTest.java
@@ -16,14 +16,9 @@
package com.android.settings.users;
-import static android.os.UserManager.SWITCHABILITY_STATUS_OK;
-import static android.os.UserManager.SWITCHABILITY_STATUS_USER_IN_CALL;
-import static android.os.UserManager.SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED;
-
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.notNull;
@@ -31,14 +26,12 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.content.Context;
import android.content.SharedPreferences;
-import android.content.pm.UserInfo;
-import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.UserHandle;
import android.os.UserManager;
@@ -49,13 +42,14 @@
import android.view.MenuItem;
import androidx.fragment.app.FragmentActivity;
+import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
import com.android.settings.testutils.shadow.ShadowUserManager;
-import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedPreference;
import org.junit.After;
@@ -63,7 +57,6 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.AdditionalMatchers;
-import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
@@ -72,7 +65,6 @@
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -81,18 +73,7 @@
public class UserSettingsTest {
private static final String KEY_USER_GUEST = "user_guest";
- private static final int ACTIVE_USER_ID = 0;
- private static final int INACTIVE_ADMIN_USER_ID = 1;
- private static final int INACTIVE_SECONDARY_USER_ID = 14;
- private static final int INACTIVE_RESTRICTED_USER_ID = 21;
- private static final int INACTIVE_GUEST_USER_ID = 23;
- private static final int MANAGED_USER_ID = 11;
- private static final String ADMIN_USER_NAME = "Owner";
- private static final String SECONDARY_USER_NAME = "Tom";
- private static final String RESTRICTED_USER_NAME = "Bob";
- private static final String GUEST_USER_NAME = "Guest";
- private static final String MANAGED_USER_NAME = "Work profile";
- private int mProvisionedBackupValue;
+ private int mProvisioned;
@Mock
private Drawable mDefaultIconDrawable;
@@ -101,10 +82,6 @@
@Mock
private UserPreference mMePreference;
@Mock
- private RestrictedPreference mAddUserPreference;
- @Mock
- private RestrictedPreference mAddGuestPreference;
- @Mock
private UserManager mUserManager;
private FragmentActivity mActivity;
@@ -118,7 +95,6 @@
mActivity = spy(ActivityController.of(new FragmentActivity()).get());
mContext = spy(RuntimeEnvironment.application);
mUserCapabilities = UserCapabilities.create(mContext);
- mUserCapabilities.mUserSwitcherEnabled = true;
mFragment = spy(new UserSettings());
ReflectionHelpers.setField(mFragment, "mAddUserWhenLockedPreferenceController",
@@ -129,41 +105,100 @@
ReflectionHelpers.setField(mFragment, "mUserCaps", mUserCapabilities);
ReflectionHelpers.setField(mFragment, "mDefaultIconDrawable", mDefaultIconDrawable);
ReflectionHelpers.setField(mFragment, "mAddingUser", false);
+ mFragment.mMePreference = mMePreference;
- doReturn(mUserManager).when(mActivity).getSystemService(UserManager.class);
-
+ when((Object) mActivity.getSystemService(UserManager.class)).thenReturn(mUserManager);
doReturn(mActivity).when(mFragment).getActivity();
doReturn(mContext).when(mFragment).getContext();
doReturn(mMockPreferenceManager).when(mFragment).getPreferenceManager();
doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
-
- mProvisionedBackupValue = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.DEVICE_PROVISIONED, 0);
- Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.DEVICE_PROVISIONED, 1); //default state
-
- final SharedPreferences prefs = mock(SharedPreferences.class);
-
- doReturn(prefs).when(mMockPreferenceManager).getSharedPreferences();
- doReturn(mContext).when(mMockPreferenceManager).getContext();
- doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
-
- mFragment.mMePreference = mMePreference;
- mFragment.mAddUser = mAddUserPreference;
- mFragment.mAddGuest = mAddGuestPreference;
- mFragment.mUserListCategory = mock(PreferenceCategory.class);
+ mProvisioned = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.DEVICE_PROVISIONED, 0);
+ final SharedPreferences prefs = mock(SharedPreferences .class);
+ when(mMockPreferenceManager.getSharedPreferences()).thenReturn(prefs);
+ when(mMockPreferenceManager.getContext()).thenReturn(mContext);
}
@After
public void tearDown() {
Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.DEVICE_PROVISIONED, mProvisionedBackupValue);
+ Settings.Global.DEVICE_PROVISIONED, mProvisioned);
}
@Test
public void testAssignDefaultPhoto_ContextNull_ReturnFalseAndNotCrash() {
// Should not crash here
- assertThat(UserSettings.assignDefaultPhoto(null, ACTIVE_USER_ID)).isFalse();
+ assertThat(UserSettings.assignDefaultPhoto(null, 0)).isFalse();
+ }
+
+ @Test
+ public void updateUserList_cannotSwitchUser_shouldNotBeSelectableForGuest() {
+ final RestrictedPreference addUser = spy(new RestrictedPreference(mContext));
+ final PreferenceGroup userListCategory = spy(new PreferenceCategory(mContext));
+
+ mUserCapabilities.mIsGuest = false;
+ mUserCapabilities.mCanAddGuest = true;
+ mUserCapabilities.mDisallowAddUser = false;
+ mUserCapabilities.mDisallowSwitchUser = false;
+ mUserCapabilities.mUserSwitcherEnabled = true;
+
+ mFragment.mUserListCategory = userListCategory;
+ mFragment.mAddUser = addUser;
+
+ when(mUserManager.canSwitchUsers()).thenReturn(false);
+ doReturn(mMockPreferenceManager).when(mFragment).getPreferenceManager();
+ doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
+ doReturn(mMockPreferenceManager).when(userListCategory).getPreferenceManager();
+
+ mFragment.updateUserList();
+
+ final Preference guest = userListCategory.findPreference(KEY_USER_GUEST);
+ assertThat(guest.isSelectable()).isFalse();
+ }
+
+ @Test
+ public void updateUserList_cannotSwitchUser_shouldDisableAddUser() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.DEVICE_PROVISIONED, 1);
+ final RestrictedPreference addUser = spy(new RestrictedPreference(mContext));
+ final PreferenceGroup userListCategory = spy(new PreferenceCategory(mContext));
+
+ mUserCapabilities.mCanAddUser = true;
+ mUserCapabilities.mDisallowAddUser = false;
+ mUserCapabilities.mUserSwitcherEnabled = true;
+
+ mFragment.mUserListCategory = userListCategory;
+ mFragment.mAddUser = addUser;
+
+ when(mUserManager.canSwitchUsers()).thenReturn(false);
+ when(mUserManager.canAddMoreUsers()).thenReturn(true);
+ doReturn(mMockPreferenceManager).when(mFragment).getPreferenceManager();
+ doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
+ doReturn(mMockPreferenceManager).when(userListCategory).getPreferenceManager();
+
+ mFragment.updateUserList();
+
+ assertThat(addUser.isEnabled()).isFalse();
+ }
+
+ @Test
+ public void updateUserList_cannotAddUserButCanSwitchUser_shouldNotShowAddUser() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.DEVICE_PROVISIONED, 1);
+ final RestrictedPreference addUser = mock(RestrictedPreference.class);
+
+ mUserCapabilities.mCanAddUser = false;
+ mUserCapabilities.mDisallowAddUser = true;
+ mUserCapabilities.mUserSwitcherEnabled = true;
+
+ mFragment.mUserListCategory = mock(PreferenceCategory.class);
+ mFragment.mAddUser = addUser;
+
+ doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
+
+ mFragment.updateUserList();
+
+ verify(addUser, never()).setVisible(true);
}
@Test
@@ -183,7 +218,7 @@
ShadowDevicePolicyManager.getShadow().setDeviceOwnerComponentOnAnyUser(
new ComponentName("test", "test"));
- doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
+ doReturn(true).when(mUserManager).canSwitchUsers();
mUserCapabilities.mIsAdmin = false;
Menu menu = mock(Menu.class);
@@ -208,7 +243,7 @@
@Test
public void withoutDisallowRemoveUser_ShouldNotDisableRemoveUser() {
// Arrange
- doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
+ doReturn(true).when(mUserManager).canSwitchUsers();
mUserCapabilities.mIsAdmin = false;
Menu menu = mock(Menu.class);
@@ -231,457 +266,44 @@
@Test
public void updateUserList_canAddUserAndSwitchUser_shouldShowAddUser() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.DEVICE_PROVISIONED, 1);
+ final RestrictedPreference addUser = mock(RestrictedPreference.class);
+
mUserCapabilities.mCanAddUser = true;
- doReturn(true).when(mUserManager).canAddMoreUsers();
- doReturn(true).when(mAddUserPreference).isEnabled();
- doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
+ mUserCapabilities.mDisallowAddUser = false;
+ mUserCapabilities.mUserSwitcherEnabled = true;
+
+ mFragment.mAddUser = addUser;
+ mFragment.mUserListCategory = mock(PreferenceCategory.class);
+
+ doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
+ doReturn("Test summary").when(mFragment).getString(anyInt(), anyInt());
mFragment.updateUserList();
- verify(mAddUserPreference).setVisible(true);
- verify(mAddUserPreference).setSummary(null);
- verify(mAddUserPreference).setEnabled(true);
- verify(mAddUserPreference).setDisabledByAdmin(null);
- verify(mAddUserPreference).setSelectable(true);
+ verify(addUser).setVisible(true);
}
@Test
- public void updateUserList_canAddGuestAndSwitchUser_shouldShowAddGuest() {
- mUserCapabilities.mCanAddGuest = true;
- doReturn(true).when(mUserManager).canAddMoreUsers();
- doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
+ public void updateUserList_addUserDisallowedByAdmin_shouldShowAddUserDisabled() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.DEVICE_PROVISIONED, 1);
+ final RestrictedPreference addUser = mock(RestrictedPreference.class);
- mFragment.updateUserList();
-
- verify(mAddGuestPreference).setVisible(true);
- verify(mAddGuestPreference).setEnabled(true);
- verify(mAddGuestPreference).setIcon(any(Drawable.class));
- verify(mAddGuestPreference).setSelectable(true);
- }
-
- @Test
- public void updateUserList_cannotSwitchUser_shouldDisableAddUser() {
- mUserCapabilities.mCanAddUser = true;
- doReturn(true).when(mUserManager).canAddMoreUsers();
- doReturn(true).when(mAddUserPreference).isEnabled();
- doReturn(SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED)
- .when(mUserManager).getUserSwitchability();
-
- mFragment.updateUserList();
-
- verify(mAddUserPreference).setVisible(true);
- verify(mAddUserPreference).setSummary(null);
- verify(mAddUserPreference).setEnabled(false);
- verify(mAddUserPreference).setSelectable(true);
- }
-
- @Test
- public void updateUserList_canNotAddMoreUsers_shouldDisableAddUserWithSummary() {
- doReturn(false).when(mUserManager).canAddMoreUsers();
- doReturn(false).when(mAddUserPreference).isEnabled();
- doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
- doReturn(4).when(mFragment).getRealUsersCount();
-
- mFragment.updateUserList();
-
- verify(mAddUserPreference).setVisible(true);
- verify(mAddUserPreference).setSummary("You can add up to 4 users");
- verify(mAddUserPreference).setEnabled(false);
- verify(mAddUserPreference).setSelectable(true);
- }
-
- @Test
- public void updateUserList_cannotSwitchUser_shouldDisableAddGuest() {
- mUserCapabilities.mCanAddGuest = true;
- doReturn(true).when(mUserManager).canAddMoreUsers();
- doReturn(SWITCHABILITY_STATUS_USER_IN_CALL).when(mUserManager).getUserSwitchability();
-
- mFragment.updateUserList();
-
- verify(mAddGuestPreference).setVisible(true);
- verify(mAddGuestPreference).setEnabled(false);
- verify(mAddGuestPreference).setIcon(any(Drawable.class));
- verify(mAddGuestPreference).setSelectable(true);
- }
-
- @Test
- public void updateUserList_addUserDisallowedByAdmin_shouldShowDisabledAddUser() {
- RestrictedLockUtils.EnforcedAdmin enforcedAdmin = mock(
- RestrictedLockUtils.EnforcedAdmin.class);
- mUserCapabilities.mEnforcedAdmin = enforcedAdmin;
mUserCapabilities.mCanAddUser = false;
mUserCapabilities.mDisallowAddUser = true;
mUserCapabilities.mDisallowAddUserSetByAdmin = true;
- doReturn(true).when(mAddUserPreference).isEnabled();
+ mUserCapabilities.mUserSwitcherEnabled = true;
+
+ mFragment.mUserListCategory = mock(PreferenceCategory.class);
+ mFragment.mAddUser = addUser;
+
+ doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
mFragment.updateUserList();
- verify(mAddUserPreference).setVisible(true);
- ArgumentCaptor<RestrictedLockUtils.EnforcedAdmin> captor = ArgumentCaptor.forClass(
- RestrictedLockUtils.EnforcedAdmin.class);
- verify(mAddUserPreference).setDisabledByAdmin(captor.capture());
- assertThat(captor.getValue()).isEqualTo(enforcedAdmin);
+ verify(addUser).setVisible(true);
+ assertThat(addUser.isEnabled()).isFalse();
}
-
- @Test
- public void updateUserList_cannotAddUserButCanSwitchUser_shouldNotShowAddUser() {
- mUserCapabilities.mCanAddUser = false;
-
- mFragment.updateUserList();
-
- verify(mAddUserPreference).setVisible(false);
- }
-
- @Test
- public void updateUserList_canNotAddGuest_shouldNotShowAddGuest() {
- mUserCapabilities.mCanAddGuest = false;
-
- mFragment.updateUserList();
-
- verify(mAddGuestPreference).setVisible(false);
- }
-
- @Test
- public void updateUserList_notProvisionedDevice_shouldNotShowAddUser() {
- Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.DEVICE_PROVISIONED, 0);
- mUserCapabilities.mCanAddUser = true;
-
- mFragment.updateUserList();
-
- verify(mAddUserPreference).setVisible(false);
- }
-
- @Test
- public void updateUserList_notProvisionedDevice_shouldNotShowAddGuest() {
- Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.DEVICE_PROVISIONED, 0);
- mUserCapabilities.mCanAddGuest = true;
-
- mFragment.updateUserList();
-
- verify(mAddGuestPreference).setVisible(false);
- }
-
- @Test
- public void updateUserList_userSwitcherDisabled_shouldNotShowAddUser() {
- mUserCapabilities.mCanAddUser = true;
- mUserCapabilities.mUserSwitcherEnabled = false;
-
- mFragment.updateUserList();
-
- verify(mAddUserPreference).setVisible(false);
- }
-
- @Test
- public void updateUserList_userSwitcherDisabled_shouldNotShowAddGuest() {
- mUserCapabilities.mCanAddGuest = true;
- mUserCapabilities.mUserSwitcherEnabled = false;
-
- mFragment.updateUserList();
-
- verify(mAddGuestPreference).setVisible(false);
- }
-
- @Test
- public void updateUserList_shouldAddAdminUserPreference() {
- givenUsers(getAdminUser(true));
-
- mFragment.updateUserList();
-
- ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
- verify(mFragment.mUserListCategory).addPreference(captor.capture());
- UserPreference adminPref = captor.getValue();
- assertThat(adminPref).isSameAs(mMePreference);
- }
-
- @Test
- public void updateUserList_existingGuest_shouldAddGuestUserPreference() {
- givenUsers(getAdminUser(true), getGuest(false));
-
- mFragment.updateUserList();
-
- ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
- verify(mFragment.mUserListCategory, times(2))
- .addPreference(captor.capture());
- UserPreference guestPref = captor.getAllValues().get(1);
- assertThat(guestPref.getUserId()).isEqualTo(INACTIVE_GUEST_USER_ID);
- assertThat(guestPref.getTitle()).isEqualTo("Guest");
- assertThat(guestPref.getIcon()).isNotNull();
- assertThat(guestPref.getKey()).isEqualTo(KEY_USER_GUEST);
- assertThat(guestPref.isEnabled()).isEqualTo(true);
- assertThat(guestPref.isSelectable()).isEqualTo(true);
- assertThat(guestPref.getOnPreferenceClickListener()).isSameAs(mFragment);
- }
-
- @Test
- public void updateUserList_existingSecondaryUser_shouldAddSecondaryUserPreference() {
- givenUsers(getAdminUser(true), getSecondaryUser(false));
-
- mFragment.updateUserList();
-
- ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
- verify(mFragment.mUserListCategory, times(2))
- .addPreference(captor.capture());
- UserPreference userPref = captor.getAllValues().get(1);
- assertThat(userPref.getUserId()).isEqualTo(INACTIVE_SECONDARY_USER_ID);
- assertThat(userPref.getTitle()).isEqualTo(SECONDARY_USER_NAME);
- assertThat(userPref.getIcon()).isNotNull();
- assertThat(userPref.getKey()).isEqualTo("id=" + INACTIVE_SECONDARY_USER_ID);
- assertThat(userPref.isEnabled()).isEqualTo(true);
- assertThat(userPref.isSelectable()).isEqualTo(true);
- assertThat(userPref.getOnPreferenceClickListener()).isSameAs(mFragment);
- }
-
- @Test
- public void updateUserList_existingRestrictedUser_shouldAddRestrictedUserPreference() {
- givenUsers(getAdminUser(true), getRestrictedUser(false));
-
- mFragment.updateUserList();
-
- ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
- verify(mFragment.mUserListCategory, times(2))
- .addPreference(captor.capture());
- UserPreference userPref = captor.getAllValues().get(1);
- assertThat(userPref.getUserId()).isEqualTo(INACTIVE_RESTRICTED_USER_ID);
- assertThat(userPref.getTitle()).isEqualTo(RESTRICTED_USER_NAME);
- assertThat(userPref.getIcon()).isNotNull();
- assertThat(userPref.getKey()).isEqualTo("id=" + INACTIVE_RESTRICTED_USER_ID);
- assertThat(userPref.getSummary()).isEqualTo("Restricted profile");
- assertThat(userPref.isEnabled()).isEqualTo(true);
- assertThat(userPref.isSelectable()).isEqualTo(true);
- assertThat(userPref.getOnPreferenceClickListener()).isSameAs(mFragment);
- }
-
- @Test
- public void updateUserList_existingManagedUser_shouldNotAddUserPreference() {
- givenUsers(getAdminUser(true), getManagedUser());
-
- mFragment.updateUserList();
-
- ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
- verify(mFragment.mUserListCategory).addPreference(captor.capture());
- List<UserPreference> userPreferences = captor.getAllValues();
- assertThat(userPreferences.size()).isEqualTo(1);
- assertThat(userPreferences.get(0).getUserId()).isEqualTo(ACTIVE_USER_ID);
- }
-
- @Test
- public void updateUserList_uninitializedRestrictedUser_shouldAddUserPreference() {
- UserInfo restrictedUser = getRestrictedUser(false);
- removeFlag(restrictedUser, UserInfo.FLAG_INITIALIZED);
- givenUsers(getAdminUser(true), restrictedUser);
- doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
- mUserCapabilities.mDisallowSwitchUser = false;
-
- mFragment.updateUserList();
-
- ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
- verify(mFragment.mUserListCategory, times(2))
- .addPreference(captor.capture());
- UserPreference userPref = captor.getAllValues().get(1);
- assertThat(userPref.getUserId()).isEqualTo(INACTIVE_RESTRICTED_USER_ID);
- assertThat(userPref.getTitle()).isEqualTo(RESTRICTED_USER_NAME);
- assertThat(userPref.getIcon()).isNotNull();
- assertThat(userPref.getKey()).isEqualTo("id=" + INACTIVE_RESTRICTED_USER_ID);
- assertThat(userPref.getSummary()).isEqualTo("Not set up - Restricted profile");
- assertThat(userPref.isEnabled()).isEqualTo(true);
- assertThat(userPref.isSelectable()).isEqualTo(true);
- assertThat(userPref.getOnPreferenceClickListener()).isSameAs(mFragment);
- }
-
- @Test
- public void updateUserList_uninitializedUserAndCanNotSwitchUser_shouldDisablePref() {
- UserInfo uninitializedUser = getSecondaryUser(false);
- removeFlag(uninitializedUser, UserInfo.FLAG_INITIALIZED);
- givenUsers(getAdminUser(true), uninitializedUser);
- doReturn(SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED)
- .when(mUserManager).getUserSwitchability();
- mUserCapabilities.mDisallowSwitchUser = false;
-
- mFragment.updateUserList();
-
- ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
- verify(mFragment.mUserListCategory, times(2))
- .addPreference(captor.capture());
- UserPreference userPref = captor.getAllValues().get(1);
- assertThat(userPref.getUserId()).isEqualTo(INACTIVE_SECONDARY_USER_ID);
- assertThat(userPref.getTitle()).isEqualTo(SECONDARY_USER_NAME);
- assertThat(userPref.getIcon()).isNotNull();
- assertThat(userPref.getKey()).isEqualTo("id=" + INACTIVE_SECONDARY_USER_ID);
- assertThat(userPref.getSummary()).isEqualTo("Not set up");
- assertThat(userPref.isEnabled()).isEqualTo(false);
- assertThat(userPref.isSelectable()).isEqualTo(true);
- assertThat(userPref.getOnPreferenceClickListener()).isSameAs(mFragment);
- }
-
- @Test
- public void updateUserList_guestWithoutInitializedFlag_shouldNotSetSummary() {
- UserInfo guest = getGuest(false);
- removeFlag(guest, UserInfo.FLAG_INITIALIZED);
- givenUsers(getAdminUser(true), guest);
-
- mFragment.updateUserList();
-
- ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
- verify(mFragment.mUserListCategory, times(2))
- .addPreference(captor.capture());
- UserPreference userPref = captor.getAllValues().get(1);
- assertThat(userPref.getUserId()).isEqualTo(INACTIVE_GUEST_USER_ID);
- assertThat(userPref.getSummary()).isNull();
- }
-
- @Test
- public void updateUserList_activeUserWithoutInitializedFlag_shouldNotSetSummary() {
- UserInfo activeUser = getSecondaryUser(true);
- removeFlag(activeUser, UserInfo.FLAG_INITIALIZED);
- givenUsers(activeUser);
-
- mFragment.updateUserList();
-
- ArgumentCaptor<UserPreference> captor = ArgumentCaptor.forClass(UserPreference.class);
- verify(mFragment.mUserListCategory).addPreference(captor.capture());
- UserPreference userPref = captor.getValue();
- assertThat(userPref.getUserId()).isEqualTo(ACTIVE_USER_ID);
- assertThat(userPref.getSummary()).isNull();
- }
-
- @Test
- public void updateUserList_guestIsAlreadyCreated_shouldNotShowAddGuest() {
- givenUsers(getAdminUser(true), getGuest(true));
- mUserCapabilities.mCanAddGuest = true;
-
- mFragment.updateUserList();
-
- verify(mAddGuestPreference).setVisible(false);
- }
-
- @Test
- public void updateUserList_userIconLoaded_shouldNotLoadIcon() {
- UserInfo currentUser = getAdminUser(true);
- currentUser.iconPath = "/data/system/users/0/photo.png";
- givenUsers(currentUser);
- mFragment.mUserIcons.put(ACTIVE_USER_ID,
- Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888));
-
- mFragment.updateUserList();
-
- verify(mUserManager, never()).getUserIcon(anyInt());
- // updateUserList should be called only once
- verify(mUserManager).getUsers(true);
- }
-
- @Test
- public void updateUserList_userIconMissing_shouldLoadIcon() {
- UserInfo currentUser = getAdminUser(true);
- currentUser.iconPath = "/data/system/users/0/photo.png";
- givenUsers(currentUser);
- // create a non-empty sparsearray
- mFragment.mUserIcons.put(5, Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888));
- Bitmap userIcon = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
- doReturn(userIcon).when(mUserManager).getUserIcon(ACTIVE_USER_ID);
-
- mFragment.updateUserList();
-
- verify(mUserManager).getUserIcon(ACTIVE_USER_ID);
- // updateUserList should be called another time after loading the icons
- verify(mUserManager, times(2)).getUsers(true);
- }
-
- @Test
- public void getRealUsersCount_onlyAdmin_shouldCount() {
- givenUsers(getAdminUser(true));
-
- int result = mFragment.getRealUsersCount();
-
- assertThat(result).isEqualTo(1);
- verify(mUserManager).getUsers();
- }
-
- @Test
- public void getRealUsersCount_secondaryUser_shouldCount() {
- givenUsers(getAdminUser(true), getSecondaryUser(false));
-
- int result = mFragment.getRealUsersCount();
-
- assertThat(result).isEqualTo(2);
- verify(mUserManager).getUsers();
- }
-
- @Test
- public void getRealUsersCount_restrictedUser_shouldCount() {
- givenUsers(getAdminUser(true), getSecondaryUser(false));
-
- int result = mFragment.getRealUsersCount();
-
- assertThat(result).isEqualTo(2);
- verify(mUserManager).getUsers();
- }
-
- @Test
- public void getRealUsersCount_guest_shouldNotCount() {
- givenUsers(getAdminUser(true), getGuest(false));
-
- int result = mFragment.getRealUsersCount();
-
- assertThat(result).isEqualTo(1);
- verify(mUserManager).getUsers();
- }
-
- @Test
- public void getRealUsersCount_managedUser_shouldNotCount() {
- givenUsers(getAdminUser(true), getManagedUser());
-
- int result = mFragment.getRealUsersCount();
-
- assertThat(result).isEqualTo(1);
- verify(mUserManager).getUsers();
- }
-
- private void givenUsers(UserInfo... userInfo) {
- List<UserInfo> users = Arrays.asList(userInfo);
- doReturn(users).when(mUserManager).getUsers();
- doReturn(users).when(mUserManager).getUsers(anyBoolean());
- }
-
- private static void removeFlag(UserInfo userInfo, int flag) {
- userInfo.flags &= ~flag;
- }
-
- private static UserInfo getAdminUser(boolean active) {
- return new UserInfo(active ? ACTIVE_USER_ID : INACTIVE_ADMIN_USER_ID, ADMIN_USER_NAME,
- null,
- UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_ADMIN,
- UserManager.USER_TYPE_FULL_SYSTEM);
- }
-
- private static UserInfo getSecondaryUser(boolean active) {
- return new UserInfo(active ? ACTIVE_USER_ID : INACTIVE_SECONDARY_USER_ID,
- SECONDARY_USER_NAME, null,
- UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED,
- UserManager.USER_TYPE_FULL_SECONDARY);
- }
-
- private static UserInfo getRestrictedUser(boolean active) {
- return new UserInfo(active ? ACTIVE_USER_ID : INACTIVE_RESTRICTED_USER_ID,
- RESTRICTED_USER_NAME, null,
- UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_RESTRICTED,
- UserManager.USER_TYPE_FULL_RESTRICTED);
- }
-
- private static UserInfo getManagedUser() {
- return new UserInfo(MANAGED_USER_ID,
- MANAGED_USER_NAME, null,
- UserInfo.FLAG_PROFILE | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_MANAGED_PROFILE,
- UserManager.USER_TYPE_PROFILE_MANAGED);
- }
-
- private static UserInfo getGuest(boolean active) {
- return new UserInfo(active ? ACTIVE_USER_ID : INACTIVE_GUEST_USER_ID, GUEST_USER_NAME,
- null,
- UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_GUEST,
- UserManager.USER_TYPE_FULL_GUEST);
- }
-
-
}