Add a switchbar to turn off multi-user feature entirely
Change-Id: Ibf88bf37899af5065c68aeb2337acd4ee48bc13c Fixes: 72319180 Test: robotest on new controller. Manual test on UserSettings fragment.
This commit is contained in:
@@ -31,7 +31,8 @@
|
||||
|
||||
<com.android.settingslib.RestrictedSwitchPreference
|
||||
android:key="security_lockscreen_add_users_when_locked"
|
||||
android:title="@string/user_add_on_lockscreen_menu" />
|
||||
android:title="@string/user_add_on_lockscreen_menu"
|
||||
settings:controller="com.android.settings.users.AddUserWhenLockedPreferenceController" />
|
||||
|
||||
<com.android.settingslib.RestrictedPreference
|
||||
android:key="owner_info_settings"
|
||||
|
@@ -21,7 +21,6 @@ package com.android.settings.core;
|
||||
*/
|
||||
public class FeatureFlags {
|
||||
public static final String BATTERY_DISPLAY_APP_LIST = "settings_battery_display_app_list";
|
||||
public static final String ZONE_PICKER_V2 = "settings_zone_picker_v2";
|
||||
public static final String BLUETOOTH_WHILE_DRIVING = "settings_bluetooth_while_driving";
|
||||
public static final String DATA_USAGE_SETTINGS_V2 = "settings_data_usage_v2";
|
||||
public static final String AUDIO_SWITCHER_SETTINGS = "settings_audio_switcher";
|
||||
|
@@ -29,7 +29,6 @@ import com.android.settings.gestures.DoubleTapScreenPreferenceController;
|
||||
import com.android.settings.gestures.PickupGesturePreferenceController;
|
||||
import com.android.settings.notification.LockScreenNotificationPreferenceController;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.users.AddUserWhenLockedPreferenceController;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
@@ -109,8 +108,6 @@ public class LockscreenDashboardFragment extends DashboardFragment
|
||||
KEY_LOCK_SCREEN_NOTIFICATON_WORK_PROFILE);
|
||||
lifecycle.addObserver(notificationController);
|
||||
controllers.add(notificationController);
|
||||
controllers.add(new AddUserWhenLockedPreferenceController(
|
||||
context, KEY_ADD_USER_FROM_LOCK_SCREEN, lifecycle));
|
||||
mOwnerInfoPreferenceController =
|
||||
new OwnerInfoPreferenceController(context, this, lifecycle);
|
||||
controllers.add(mOwnerInfoPreferenceController);
|
||||
@@ -147,8 +144,6 @@ public class LockscreenDashboardFragment extends DashboardFragment
|
||||
Context context) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
controllers.add(new LockScreenNotificationPreferenceController(context));
|
||||
controllers.add(new AddUserWhenLockedPreferenceController(context,
|
||||
KEY_ADD_USER_FROM_LOCK_SCREEN, null /* lifecycle */));
|
||||
controllers.add(new OwnerInfoPreferenceController(
|
||||
context, null /* fragment */, null /* lifecycle */));
|
||||
return controllers;
|
||||
|
@@ -16,72 +16,53 @@
|
||||
package com.android.settings.users;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings.Global;
|
||||
import android.provider.Settings;
|
||||
|
||||
import com.android.settings.core.TogglePreferenceController;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
public class AddUserWhenLockedPreferenceController extends TogglePreferenceController {
|
||||
|
||||
public class AddUserWhenLockedPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener,
|
||||
LifecycleObserver, OnPause, OnResume {
|
||||
|
||||
private final String mPrefKey;
|
||||
private final UserCapabilities mUserCaps;
|
||||
private boolean mShouldUpdateUserList;
|
||||
|
||||
public AddUserWhenLockedPreferenceController(Context context, String key, Lifecycle lifecycle) {
|
||||
super(context);
|
||||
mPrefKey = key;
|
||||
public AddUserWhenLockedPreferenceController(Context context, String key) {
|
||||
super(context, key);
|
||||
mUserCaps = UserCapabilities.create(context);
|
||||
if (lifecycle != null) {
|
||||
lifecycle.addObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
RestrictedSwitchPreference restrictedSwitchPreference =
|
||||
super.updateState(preference);
|
||||
mUserCaps.updateAddUserCapabilities(mContext);
|
||||
final RestrictedSwitchPreference restrictedSwitchPreference =
|
||||
(RestrictedSwitchPreference) preference;
|
||||
int value = Global.getInt(mContext.getContentResolver(), Global.ADD_USERS_WHEN_LOCKED, 0);
|
||||
restrictedSwitchPreference.setChecked(value == 1);
|
||||
restrictedSwitchPreference.setDisabledByAdmin(
|
||||
mUserCaps.disallowAddUser() ? mUserCaps.getEnforcedAdmin() : null);
|
||||
restrictedSwitchPreference.setVisible(mUserCaps.mUserSwitcherEnabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
Boolean value = (Boolean) newValue;
|
||||
Global.putInt(mContext.getContentResolver(),
|
||||
Global.ADD_USERS_WHEN_LOCKED, value != null && value ? 1 : 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
mShouldUpdateUserList = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
if (mShouldUpdateUserList) {
|
||||
mUserCaps.updateAddUserCapabilities(mContext);
|
||||
public int getAvailabilityStatus() {
|
||||
if (!mUserCaps.isAdmin()) {
|
||||
return DISABLED_FOR_USER;
|
||||
} else if (mUserCaps.disallowAddUser() || mUserCaps.disallowAddUserSetByAdmin()) {
|
||||
return DISABLED_FOR_USER;
|
||||
} else {
|
||||
return mUserCaps.mUserSwitcherEnabled ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return mUserCaps.isAdmin() &&
|
||||
(!mUserCaps.disallowAddUser() || mUserCaps.disallowAddUserSetByAdmin());
|
||||
public boolean isChecked() {
|
||||
return Settings.Global.getInt(mContext.getContentResolver(),
|
||||
Settings.Global.ADD_USERS_WHEN_LOCKED, 0) == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return mPrefKey;
|
||||
public boolean setChecked(boolean isChecked) {
|
||||
return Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.ADD_USERS_WHEN_LOCKED, isChecked ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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 android.content.Context;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settingslib.widget.FooterPreference;
|
||||
import com.android.settingslib.widget.FooterPreferenceMixin;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
public class MultiUserFooterPreferenceController extends BasePreferenceController {
|
||||
|
||||
@VisibleForTesting
|
||||
final UserCapabilities mUserCaps;
|
||||
|
||||
private FooterPreferenceMixin mFooterMixin;
|
||||
|
||||
public MultiUserFooterPreferenceController(Context context) {
|
||||
super(context, "dummy_key");
|
||||
mUserCaps = UserCapabilities.create(context);
|
||||
}
|
||||
|
||||
public MultiUserFooterPreferenceController setFooterMixin(FooterPreferenceMixin footerMixin) {
|
||||
mFooterMixin = footerMixin;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return (mUserCaps.mEnabled && !mUserCaps.mUserSwitcherEnabled)
|
||||
? AVAILABLE_UNSEARCHABLE
|
||||
: DISABLED_FOR_USER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
mUserCaps.updateAddUserCapabilities(mContext);
|
||||
final FooterPreference pref = mFooterMixin.createFooterPreference();
|
||||
pref.setTitle(R.string.user_settings_footer_text);
|
||||
pref.setVisible(isAvailable());
|
||||
}
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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 android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settings.widget.SwitchWidgetController;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStart;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStop;
|
||||
|
||||
public class MultiUserSwitchBarController implements SwitchWidgetController.OnSwitchChangeListener,
|
||||
LifecycleObserver, OnStart, OnStop {
|
||||
|
||||
interface OnMultiUserSwitchChangedListener {
|
||||
void onMultiUserSwitchChanged(boolean newState);
|
||||
}
|
||||
|
||||
private static final String TAG = "MultiUserSwitchBarCtrl";
|
||||
private final Context mContext;
|
||||
private final SwitchWidgetController mSwitchBar;
|
||||
private final UserCapabilities mUserCapabilities;
|
||||
private final OnMultiUserSwitchChangedListener mListener;
|
||||
|
||||
MultiUserSwitchBarController(Context context, SwitchWidgetController switchBar,
|
||||
OnMultiUserSwitchChangedListener listener) {
|
||||
mContext = context;
|
||||
mSwitchBar = switchBar;
|
||||
mListener = listener;
|
||||
mUserCapabilities = UserCapabilities.create(context);
|
||||
mSwitchBar.setChecked(mUserCapabilities.mUserSwitcherEnabled);
|
||||
mSwitchBar.setEnabled(!mUserCapabilities.mDisallowSwitchUser
|
||||
&& !mUserCapabilities.mIsGuest && mUserCapabilities.isAdmin());
|
||||
mSwitchBar.setListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
mSwitchBar.startListening();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
mSwitchBar.stopListening();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSwitchToggled(boolean isChecked) {
|
||||
Log.d(TAG, "Toggling multi-user feature enabled state to: " + isChecked);
|
||||
final boolean success = Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.USER_SWITCHER_ENABLED, isChecked ? 1 : 0);
|
||||
if (success && mListener != null) {
|
||||
mListener.onMultiUserSwitchChanged(isChecked);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
@@ -22,6 +22,7 @@ import android.content.pm.UserInfo;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
|
||||
@@ -31,13 +32,15 @@ public class UserCapabilities {
|
||||
boolean mCanAddRestrictedProfile = true;
|
||||
boolean mIsAdmin;
|
||||
boolean mIsGuest;
|
||||
boolean mUserSwitcherEnabled;
|
||||
boolean mCanAddGuest;
|
||||
boolean mDisallowAddUser;
|
||||
boolean mDisallowAddUserSetByAdmin;
|
||||
boolean mDisallowSwitchUser;
|
||||
RestrictedLockUtils.EnforcedAdmin mEnforcedAdmin;
|
||||
|
||||
private UserCapabilities() {}
|
||||
private UserCapabilities() {
|
||||
}
|
||||
|
||||
public static UserCapabilities create(Context context) {
|
||||
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||
@@ -62,14 +65,15 @@ public class UserCapabilities {
|
||||
}
|
||||
|
||||
public void updateAddUserCapabilities(Context context) {
|
||||
final UserManager userManager =
|
||||
(UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||
mEnforcedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(context,
|
||||
UserManager.DISALLOW_ADD_USER, UserHandle.myUserId());
|
||||
final boolean hasBaseUserRestriction = RestrictedLockUtils.hasBaseUserRestriction(
|
||||
context, UserManager.DISALLOW_ADD_USER, UserHandle.myUserId());
|
||||
mDisallowAddUserSetByAdmin =
|
||||
mEnforcedAdmin != null && !hasBaseUserRestriction;
|
||||
mDisallowAddUser =
|
||||
(mEnforcedAdmin != null || hasBaseUserRestriction);
|
||||
mDisallowAddUserSetByAdmin = mEnforcedAdmin != null && !hasBaseUserRestriction;
|
||||
mDisallowAddUser = (mEnforcedAdmin != null || hasBaseUserRestriction);
|
||||
mUserSwitcherEnabled = userManager.isUserSwitcherEnabled();
|
||||
mCanAddUser = true;
|
||||
if (!mIsAdmin || UserManager.getMaxSupportedUsers() < 2
|
||||
|| !UserManager.supportsMultipleUsers()
|
||||
@@ -81,7 +85,6 @@ public class UserCapabilities {
|
||||
context.getContentResolver(), Settings.Global.ADD_USERS_WHEN_LOCKED, 0) == 1;
|
||||
mCanAddGuest = !mIsGuest && !mDisallowAddUser && canAddUsersWhenLocked;
|
||||
|
||||
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||
mDisallowSwitchUser = userManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH);
|
||||
}
|
||||
|
||||
|
@@ -48,13 +48,13 @@ import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.SimpleAdapter;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.util.UserIcons;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
@@ -62,6 +62,8 @@ import com.android.settings.dashboard.SummaryLoader;
|
||||
import com.android.settings.password.ChooseLockGeneric;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
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.RestrictedPreference;
|
||||
@@ -78,7 +80,6 @@ import java.util.List;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.annotation.WorkerThread;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.Preference.OnPreferenceClickListener;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
@@ -92,7 +93,9 @@ import androidx.preference.PreferenceScreen;
|
||||
*/
|
||||
@SearchIndexable
|
||||
public class UserSettings extends SettingsPreferenceFragment
|
||||
implements OnPreferenceClickListener, OnClickListener, DialogInterface.OnDismissListener,
|
||||
implements Preference.OnPreferenceClickListener, View.OnClickListener,
|
||||
MultiUserSwitchBarController.OnMultiUserSwitchChangedListener,
|
||||
DialogInterface.OnDismissListener,
|
||||
EditUserInfoController.OnContentChangedCallback, Indexable {
|
||||
|
||||
private static final String TAG = "UserSettings";
|
||||
@@ -155,8 +158,10 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
private SparseArray<Bitmap> mUserIcons = new SparseArray<>();
|
||||
private static SparseArray<Bitmap> sDarkDefaultUserBitmapCache = new SparseArray<>();
|
||||
|
||||
private MultiUserSwitchBarController mSwitchBarController;
|
||||
private EditUserInfoController mEditUserInfoController = new EditUserInfoController();
|
||||
private AddUserWhenLockedPreferenceController mAddUserWhenLockedPreferenceController;
|
||||
private MultiUserFooterPreferenceController mMultiUserFooterPreferenceController;
|
||||
|
||||
// A place to cache the generated default avatar
|
||||
private Drawable mDefaultIconDrawable;
|
||||
@@ -198,20 +203,37 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
return MetricsEvent.USER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
// Assume we are in a SettingsActivity. This is only safe because we currently use
|
||||
// SettingsActivity as base for all preference fragments.
|
||||
final SettingsActivity activity = (SettingsActivity) getActivity();
|
||||
final SwitchBar switchBar = activity.getSwitchBar();
|
||||
mSwitchBarController = new MultiUserSwitchBarController(activity,
|
||||
new SwitchBarController(switchBar), this /* listener */);
|
||||
getLifecycle().addObserver(mSwitchBarController);
|
||||
switchBar.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
addPreferencesFromResource(R.xml.user_settings);
|
||||
final Activity activity = getActivity();
|
||||
if (!Utils.isDeviceProvisioned(getActivity())) {
|
||||
if (!Utils.isDeviceProvisioned(activity)) {
|
||||
activity.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
mAddUserWhenLockedPreferenceController = new AddUserWhenLockedPreferenceController(
|
||||
activity, KEY_ADD_USER_WHEN_LOCKED, getLifecycle());
|
||||
activity, KEY_ADD_USER_WHEN_LOCKED);
|
||||
mMultiUserFooterPreferenceController = new MultiUserFooterPreferenceController(activity)
|
||||
.setFooterMixin(mFooterPreferenceMixin);
|
||||
|
||||
final PreferenceScreen screen = getPreferenceScreen();
|
||||
mAddUserWhenLockedPreferenceController.displayPreference(screen);
|
||||
mMultiUserFooterPreferenceController.displayPreference(screen);
|
||||
|
||||
screen.findPreference(mAddUserWhenLockedPreferenceController.getPreferenceKey())
|
||||
.setOnPreferenceChangeListener(mAddUserWhenLockedPreferenceController);
|
||||
@@ -246,7 +268,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
mAddUser = (RestrictedPreference) findPreference(KEY_ADD_USER);
|
||||
mAddUser.useAdminDisabledSummary(false);
|
||||
// Determine if add user/profile button should be visible
|
||||
if (mUserCaps.mCanAddUser && Utils.isDeviceProvisioned(getActivity())) {
|
||||
if (mUserCaps.mCanAddUser && Utils.isDeviceProvisioned(activity)) {
|
||||
mAddUser.setVisible(true);
|
||||
mAddUser.setOnPreferenceClickListener(this);
|
||||
// change label to only mention user, if restricted profiles are not supported
|
||||
@@ -260,8 +282,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
activity.registerReceiverAsUser(
|
||||
mUserChangeReceiver, UserHandle.ALL, USER_REMOVED_INTENT_FILTER, null, mHandler);
|
||||
|
||||
loadProfile();
|
||||
updateUserList();
|
||||
updateUI();
|
||||
mShouldUpdateUserList = false;
|
||||
}
|
||||
|
||||
@@ -280,9 +301,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
}
|
||||
|
||||
if (mShouldUpdateUserList) {
|
||||
mUserCaps.updateAddUserCapabilities(getActivity());
|
||||
loadProfile();
|
||||
updateUserList();
|
||||
updateUI();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,6 +362,17 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMultiUserSwitchChanged(boolean newState) {
|
||||
updateUI();
|
||||
}
|
||||
|
||||
private void updateUI() {
|
||||
mUserCaps.updateAddUserCapabilities(getActivity());
|
||||
loadProfile();
|
||||
updateUserList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads profile information for the current user.
|
||||
*/
|
||||
@@ -909,8 +939,6 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
loadIconsAsync(missingIcons);
|
||||
}
|
||||
|
||||
// Remove everything from mUserListCategory and add new users.
|
||||
mUserListCategory.removeAll();
|
||||
// If profiles are supported, mUserListCategory will have a special title
|
||||
if (mUserCaps.mCanAddRestrictedProfile) {
|
||||
mUserListCategory.setTitle(R.string.user_list_title);
|
||||
@@ -918,6 +946,20 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
mUserListCategory.setTitle(null);
|
||||
}
|
||||
|
||||
// Remove everything from mUserListCategory and add new users.
|
||||
mUserListCategory.removeAll();
|
||||
|
||||
// If multi-user is disabled, just show footer and return.
|
||||
final Preference addUserOnLockScreen = getPreferenceScreen().findPreference(
|
||||
mAddUserWhenLockedPreferenceController.getPreferenceKey());
|
||||
mAddUserWhenLockedPreferenceController.updateState(addUserOnLockScreen);
|
||||
mMultiUserFooterPreferenceController.updateState(null /* preference */);
|
||||
mAddUser.setVisible(mUserCaps.mUserSwitcherEnabled);
|
||||
mUserListCategory.setVisible(mUserCaps.mUserSwitcherEnabled);
|
||||
if (!mUserCaps.mUserSwitcherEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (UserPreference userPreference : userPreferences) {
|
||||
userPreference.setOrder(Preference.DEFAULT_ORDER);
|
||||
mUserListCategory.addPreference(userPreference);
|
||||
@@ -925,7 +967,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
|
||||
// Append Add user to the end of the list
|
||||
if ((mUserCaps.mCanAddUser || mUserCaps.mDisallowAddUserSetByAdmin) &&
|
||||
Utils.isDeviceProvisioned(getActivity())) {
|
||||
Utils.isDeviceProvisioned(context)) {
|
||||
boolean moreUsers = mUserManager.canAddMoreUsers();
|
||||
mAddUser.setEnabled(moreUsers && !mAddingUser);
|
||||
if (!moreUsers) {
|
||||
@@ -938,7 +980,6 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
mUserCaps.mDisallowAddUser ? mUserCaps.mEnforcedAdmin : null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private int getMaxRealUsers() {
|
||||
@@ -1190,8 +1231,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
@Override
|
||||
public List<String> getNonIndexableKeysFromXml(Context context, int xmlResId) {
|
||||
final List<String> niks = super.getNonIndexableKeysFromXml(context, xmlResId);
|
||||
new AddUserWhenLockedPreferenceController(
|
||||
context, KEY_ADD_USER_WHEN_LOCKED, null /* lifecycle */)
|
||||
new AddUserWhenLockedPreferenceController(context, KEY_ADD_USER_WHEN_LOCKED)
|
||||
.updateNonIndexableKeys(niks);
|
||||
new AutoSyncDataPreferenceController(context, null /* parent */)
|
||||
.updateNonIndexableKeys(niks);
|
||||
|
@@ -47,6 +47,8 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager
|
||||
private final Set<Integer> mManagedProfiles = new HashSet<>();
|
||||
private boolean mIsQuietModeEnabled = false;
|
||||
private int[] profileIdsForUser;
|
||||
private boolean mUserSwitchEnabled;
|
||||
|
||||
|
||||
@Resetter
|
||||
public void reset() {
|
||||
@@ -56,6 +58,7 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager
|
||||
mRestrictionSources.clear();
|
||||
mManagedProfiles.clear();
|
||||
mIsQuietModeEnabled = false;
|
||||
mUserSwitchEnabled = false;
|
||||
}
|
||||
|
||||
public void setUserInfo(int userHandle, UserInfo userInfo) {
|
||||
@@ -136,4 +139,13 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager
|
||||
public void setProfileIdsWithDisabled(int[] profileIds) {
|
||||
profileIdsForUser = profileIds;
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public boolean isUserSwitcherEnabled() {
|
||||
return mUserSwitchEnabled;
|
||||
}
|
||||
|
||||
public void setUserSwitcherEnabled(boolean userSwitchEnabled) {
|
||||
mUserSwitchEnabled = userSwitchEnabled;
|
||||
}
|
||||
}
|
||||
|
@@ -17,58 +17,59 @@ package com.android.settings.users;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Answers.RETURNS_DEEP_STUBS;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import android.content.Context;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings.Global;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
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.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowApplication;
|
||||
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowUserManager.class})
|
||||
public class AddUserWhenLockedPreferenceControllerTest {
|
||||
|
||||
@Mock(answer = RETURNS_DEEP_STUBS)
|
||||
private PreferenceScreen mScreen;
|
||||
@Mock(answer = RETURNS_DEEP_STUBS)
|
||||
private UserInfo mUserInfo;
|
||||
@Mock(answer = RETURNS_DEEP_STUBS)
|
||||
private UserManager mUserManager;
|
||||
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
private Lifecycle mLifecycle;
|
||||
private Context mContext;
|
||||
private ShadowUserManager mUserManager;
|
||||
private AddUserWhenLockedPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
ShadowApplication shadowContext = ShadowApplication.getInstance();
|
||||
shadowContext.setSystemService(Context.USER_SERVICE, mUserManager);
|
||||
mUserManager = ShadowUserManager.getShadow();
|
||||
mContext = shadowContext.getApplicationContext();
|
||||
mLifecycleOwner = () -> mLifecycle;
|
||||
mLifecycle = new Lifecycle(mLifecycleOwner);
|
||||
mController = new AddUserWhenLockedPreferenceController(mContext, "fake_key", mLifecycle);
|
||||
mController = new AddUserWhenLockedPreferenceController(mContext, "fake_key");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
mUserManager.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPref_NotAdmin_shouldNotDisplay() {
|
||||
when(mUserManager.getUserInfo(anyInt())).thenReturn(mUserInfo);
|
||||
mUserManager.setUserInfo(0, mUserInfo);
|
||||
when(mUserInfo.isAdmin()).thenReturn(false);
|
||||
final RestrictedSwitchPreference preference = mock(RestrictedSwitchPreference.class);
|
||||
when(preference.getKey()).thenReturn(mController.getPreferenceKey());
|
||||
|
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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 com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_USER;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
public class MultiUserFooterPreferenceControllerTest {
|
||||
|
||||
private Context mContext;
|
||||
private MultiUserFooterPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mController = new MultiUserFooterPreferenceController(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_multiUserOff_shouldReturnEnabled() {
|
||||
mController.mUserCaps.mEnabled = true;
|
||||
mController.mUserCaps.mUserSwitcherEnabled = false;
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_multiUserOn_shouldReturnDisabled() {
|
||||
mController.mUserCaps.mEnabled = true;
|
||||
mController.mUserCaps.mUserSwitcherEnabled = true;
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_FOR_USER);
|
||||
}
|
||||
}
|
@@ -17,36 +17,43 @@
|
||||
package com.android.settings.users;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
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.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowUserManager.class})
|
||||
public class UserCapabilitiesTest {
|
||||
|
||||
@Mock
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
private ShadowUserManager mUserManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mUserManager = ShadowUserManager.getShadow();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
mUserManager.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disallowUserSwitchWhenRestrictionIsSet() {
|
||||
when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(true);
|
||||
public void disallowUserSwitch_restrictionIsSet_true() {
|
||||
mUserManager.setUserRestriction(UserHandle.of(UserHandle.myUserId()),
|
||||
UserManager.DISALLOW_USER_SWITCH, true);
|
||||
|
||||
UserCapabilities userCapabilities = UserCapabilities.create(mContext);
|
||||
userCapabilities.updateAddUserCapabilities(mContext);
|
||||
@@ -55,12 +62,33 @@ public class UserCapabilitiesTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allowUserSwitchWhenRestrictionIsNotSet() {
|
||||
when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(false);
|
||||
public void disallowUserSwitch_restrictionIsNotSet_false() {
|
||||
mUserManager.setUserRestriction(UserHandle.of(UserHandle.myUserId()),
|
||||
UserManager.DISALLOW_USER_SWITCH, false);
|
||||
|
||||
UserCapabilities userCapabilities = UserCapabilities.create(mContext);
|
||||
userCapabilities.updateAddUserCapabilities(mContext);
|
||||
|
||||
assertThat(userCapabilities.mDisallowSwitchUser).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userSwitchEnabled_off() {
|
||||
mUserManager.setUserSwitcherEnabled(false);
|
||||
|
||||
final UserCapabilities userCapabilities = UserCapabilities.create(mContext);
|
||||
userCapabilities.updateAddUserCapabilities(mContext);
|
||||
|
||||
assertThat(userCapabilities.mUserSwitcherEnabled).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userSwitchEnabled_on() {
|
||||
mUserManager.setUserSwitcherEnabled(true);
|
||||
|
||||
final UserCapabilities userCapabilities = UserCapabilities.create(mContext);
|
||||
userCapabilities.updateAddUserCapabilities(mContext);
|
||||
|
||||
assertThat(userCapabilities.mUserSwitcherEnabled).isTrue();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user