Improve multi user functionality for restricted users

- Restricted users can change their name
- Improved App&Content access screen
- Remove "Turn on phone calls" from restricted user detail page

Doc: http://shortn/_Prb3SJ3xJ3
Bug: 142798722
Test: Run robo tests with this command:
  make -j64 RunSettingsRoboTests
Change-Id: I2aadf32aef52ba5ad0db7aa0cd83bac9d9941589
(cherry picked from commit f4759e00d5)
This commit is contained in:
Andras Kloczl
2020-05-18 14:53:07 +01:00
committed by András Klöczl
parent ff35a3e641
commit 106431e525
14 changed files with 311 additions and 404 deletions

View File

@@ -25,7 +25,6 @@
android:layout_width="56dip" android:layout_width="56dip"
android:layout_height="56dip" android:layout_height="56dip"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:layout_marginEnd="6dp"
android:contentDescription="@string/user_image_photo_selector" android:contentDescription="@string/user_image_photo_selector"
android:background="@*android:drawable/spinner_background_holo_dark" android:background="@*android:drawable/spinner_background_holo_dark"
android:scaleType="fitCenter"/> android:scaleType="fitCenter"/>

View File

@@ -1,129 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2013 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.
-->
<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"
android:gravity="center_vertical"
android:orientation="vertical"
android:focusable="true"
android:clickable="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="@+id/app_restrictions_pref"
android:gravity="center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:background="?android:attr/selectableItemBackground" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:minWidth="@*android:dimen/preference_icon_minWidth"
android:orientation="horizontal">
<ImageView
android:id="@android:id/icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:minWidth="48dp"
android:scaleType="centerInside"
android:layout_marginEnd="@*android:dimen/preference_item_padding_inner"/>
</LinearLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="6dip"
android:layout_marginTop="6dip"
android:layout_marginBottom="6dip"
android:layout_weight="1">
<TextView
android:id="@android:id/title"
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"/>
<TextView
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
android:layout_alignStart="@android:id/title"
android:paddingBottom="3dip"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textSize="13sp"
android:textColor="?android:attr/textColorSecondary"
android:focusable="false"
android:text="@string/user_summary_restricted_profile"
android:maxLines="4" />
</RelativeLayout>
<ImageView
android:id="@+id/delete"
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>
<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" />
</LinearLayout>

View File

@@ -25,6 +25,10 @@
android:key="enable_calling" android:key="enable_calling"
android:icon="@drawable/ic_phone" android:icon="@drawable/ic_phone"
android:title="@string/user_enable_calling_sms" /> android:title="@string/user_enable_calling_sms" />
<com.android.settingslib.RestrictedPreference
android:key="app_and_content_access"
android:icon="@drawable/ic_lock_closed"
android:title="@string/user_restrictions_title" />
<com.android.settingslib.RestrictedPreference <com.android.settingslib.RestrictedPreference
android:key="remove_user" android:key="remove_user"
android:icon="@drawable/ic_delete" android:icon="@drawable/ic_delete"

View File

@@ -30,7 +30,6 @@ import androidx.fragment.app.FragmentActivity;
import androidx.loader.app.LoaderManager; import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader; import androidx.loader.content.Loader;
import com.android.settings.users.RestrictedProfileSettings;
import com.android.settingslib.license.LicenseHtmlLoaderCompat; import com.android.settingslib.license.LicenseHtmlLoaderCompat;
import java.io.File; import java.io.File;
@@ -78,7 +77,7 @@ public class SettingsLicenseActivity extends FragmentActivity implements
@VisibleForTesting @VisibleForTesting
Uri getUriFromGeneratedHtmlFile(File generatedHtmlFile) { Uri getUriFromGeneratedHtmlFile(File generatedHtmlFile) {
return FileProvider.getUriForFile(this, RestrictedProfileSettings.FILE_PROVIDER_AUTHORITY, return FileProvider.getUriForFile(this, Utils.FILE_PROVIDER_AUTHORITY,
generatedHtmlFile); generatedHtmlFile);
} }

View File

@@ -116,6 +116,8 @@ public final class Utils extends com.android.settingslib.Utils {
private static final String TAG = "Settings"; private static final String TAG = "Settings";
public static final String FILE_PROVIDER_AUTHORITY = "com.android.settings.files";
/** /**
* Set the preference's title to the matching activity's label. * Set the preference's title to the matching activity's label.
*/ */

View File

@@ -97,15 +97,8 @@ public class AppRestrictionsFragment extends SettingsPreferenceFragment implemen
/** Key for extra passed in from calling fragment to indicate if this is a newly created user */ /** 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"; 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 mFirstTime = true;
private boolean mNewUser; private boolean mNewUser;
protected boolean mShowSwitchUser;
private boolean mAppListChanged; private boolean mAppListChanged;
protected boolean mRestrictedProfile; protected boolean mRestrictedProfile;
@@ -216,6 +209,12 @@ public class AppRestrictionsFragment extends SettingsPreferenceFragment implemen
} }
} }
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
init(icicle);
}
protected void init(Bundle icicle) { protected void init(Bundle icicle) {
if (icicle != null) { if (icicle != null) {
mUser = new UserHandle(icicle.getInt(EXTRA_USER_ID)); mUser = new UserHandle(icicle.getInt(EXTRA_USER_ID));
@@ -226,7 +225,6 @@ public class AppRestrictionsFragment extends SettingsPreferenceFragment implemen
mUser = new UserHandle(args.getInt(EXTRA_USER_ID)); mUser = new UserHandle(args.getInt(EXTRA_USER_ID));
} }
mNewUser = args.getBoolean(EXTRA_NEW_USER, false); mNewUser = args.getBoolean(EXTRA_NEW_USER, false);
mShowSwitchUser = args.getBoolean(EXTRA_SHOW_SWITCH_USER, false);
} }
} }

View File

@@ -18,8 +18,10 @@ package com.android.settings.users;
import android.app.Activity; import android.app.Activity;
import android.app.Dialog; import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.pm.UserInfo;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
@@ -77,7 +79,9 @@ public class EditUserInfoController {
} }
public void clear() { public void clear() {
mEditUserPhotoController.removeNewUserPhotoBitmapFile(); if (mEditUserPhotoController != null) {
mEditUserPhotoController.removeNewUserPhotoBitmapFile();
}
mEditUserInfoDialog = null; mEditUserInfoDialog = null;
mSavedPhoto = null; mSavedPhoto = null;
} }
@@ -116,7 +120,7 @@ public class EditUserInfoController {
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
mWaitingForActivityResult = false; mWaitingForActivityResult = false;
if (mEditUserInfoDialog != null) { if (mEditUserPhotoController != null && mEditUserInfoDialog != null) {
mEditUserPhotoController.onActivityResult(requestCode, resultCode, data); mEditUserPhotoController.onActivityResult(requestCode, resultCode, data);
} }
} }
@@ -137,6 +141,14 @@ public class EditUserInfoController {
userNameView.setText(currentUserName); userNameView.setText(currentUserName);
final ImageView userPhotoView = (ImageView) content.findViewById(R.id.user_photo); final ImageView userPhotoView = (ImageView) content.findViewById(R.id.user_photo);
boolean canChangePhoto = mUserManager != null &&
canChangePhoto(activity, mUserManager.getUserInfo(user.getIdentifier()));
if (!canChangePhoto) {
// some users can't change their photos so we need to remove suggestive
// background from the photoView
userPhotoView.setBackground(null);
}
Drawable drawable = null; Drawable drawable = null;
if (mSavedPhoto != null) { if (mSavedPhoto != null) {
drawable = CircleFramedDrawable.getInstance(activity, mSavedPhoto); drawable = CircleFramedDrawable.getInstance(activity, mSavedPhoto);
@@ -144,7 +156,10 @@ public class EditUserInfoController {
drawable = currentUserIcon; drawable = currentUserIcon;
} }
userPhotoView.setImageDrawable(drawable); userPhotoView.setImageDrawable(drawable);
mEditUserPhotoController = createEditUserPhotoController(fragment, userPhotoView, drawable); if (canChangePhoto) {
mEditUserPhotoController =
createEditUserPhotoController(fragment, userPhotoView, drawable);
}
mEditUserInfoDialog = new AlertDialog.Builder(activity) mEditUserInfoDialog = new AlertDialog.Builder(activity)
.setTitle(title) .setTitle(title)
.setView(content) .setView(content)
@@ -158,21 +173,22 @@ public class EditUserInfoController {
if (!TextUtils.isEmpty(userName)) { if (!TextUtils.isEmpty(userName)) {
if (currentUserName == null if (currentUserName == null
|| !userName.toString().equals( || !userName.toString().equals(
currentUserName.toString())) { currentUserName.toString())) {
if (callback != null) { if (callback != null) {
callback.onLabelChanged(mUser, userName.toString()); callback.onLabelChanged(mUser, userName.toString());
} }
} }
} }
// Update the photo if changed. // Update the photo if changed.
Drawable drawable = mEditUserPhotoController.getNewUserPhotoDrawable(); if (mEditUserPhotoController != null) {
if (drawable != null && !drawable.equals(currentUserIcon)) { Drawable drawable =
if (callback != null) { mEditUserPhotoController.getNewUserPhotoDrawable();
if (drawable != null && !drawable.equals(currentUserIcon)) {
if (callback != null) {
callback.onPhotoChanged(mUser, drawable); callback.onPhotoChanged(mUser, drawable);
}
} }
} }
fragment.getActivity().removeDialog(
RestrictedProfileSettings.DIALOG_ID_EDIT_USER_INFO);
} }
clear(); clear();
if (completeCallback != null) { if (completeCallback != null) {
@@ -207,6 +223,13 @@ public class EditUserInfoController {
return mEditUserInfoDialog; return mEditUserInfoDialog;
} }
@VisibleForTesting
boolean canChangePhoto(Context context, UserInfo user) {
return PhotoCapabilityUtils.canCropPhoto(context) &&
(PhotoCapabilityUtils.canChoosePhoto(context)
|| PhotoCapabilityUtils.canTakePhoto(context));
}
@VisibleForTesting @VisibleForTesting
EditUserPhotoController createEditUserPhotoController(Fragment fragment, EditUserPhotoController createEditUserPhotoController(Fragment fragment,
ImageView userPhotoView, Drawable drawable) { ImageView userPhotoView, Drawable drawable) {

View File

@@ -21,7 +21,6 @@ import android.content.ClipData;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Bitmap.Config; import android.graphics.Bitmap.Config;
@@ -52,6 +51,7 @@ import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.drawable.CircleFramedDrawable; import com.android.settingslib.drawable.CircleFramedDrawable;
@@ -141,14 +141,14 @@ public class EditUserPhotoController {
} }
private void showUpdatePhotoPopup() { private void showUpdatePhotoPopup() {
final boolean canTakePhoto = canTakePhoto(); final Context context = mImageView.getContext();
final boolean canChoosePhoto = canChoosePhoto(); final boolean canTakePhoto = PhotoCapabilityUtils.canTakePhoto(context);
final boolean canChoosePhoto = PhotoCapabilityUtils.canChoosePhoto(context);
if (!canTakePhoto && !canChoosePhoto) { if (!canTakePhoto && !canChoosePhoto) {
return; return;
} }
final Context context = mImageView.getContext();
final List<EditUserPhotoController.RestrictedMenuItem> items = new ArrayList<>(); final List<EditUserPhotoController.RestrictedMenuItem> items = new ArrayList<>();
if (canTakePhoto) { if (canTakePhoto) {
@@ -200,19 +200,6 @@ public class EditUserPhotoController {
listPopupWindow.show(); listPopupWindow.show();
} }
private boolean canTakePhoto() {
return mImageView.getContext().getPackageManager().queryIntentActivities(
new Intent(MediaStore.ACTION_IMAGE_CAPTURE),
PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
private boolean canChoosePhoto() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
return mImageView.getContext().getPackageManager().queryIntentActivities(
intent, 0).size() > 0;
}
private void takePhoto() { private void takePhoto() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
appendOutputExtra(intent, mTakePictureUri); appendOutputExtra(intent, mTakePictureUri);
@@ -369,8 +356,7 @@ public class EditUserPhotoController {
if (purge) { if (purge) {
fullPath.delete(); fullPath.delete();
} }
return FileProvider.getUriForFile(context, return FileProvider.getUriForFile(context, Utils.FILE_PROVIDER_AUTHORITY, fullPath);
RestrictedProfileSettings.FILE_PROVIDER_AUTHORITY, fullPath);
} }
File saveNewUserPhotoBitmap() { File saveNewUserPhotoBitmap() {

View File

@@ -0,0 +1,56 @@
/*
* 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 android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.provider.MediaStore;
class PhotoCapabilityUtils {
/**
* Check if the current user can perform any activity for
* android.media.action.IMAGE_CAPTURE action.
*/
static boolean canTakePhoto(Context context) {
return context.getPackageManager().queryIntentActivities(
new Intent(MediaStore.ACTION_IMAGE_CAPTURE),
PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
}
/**
* Check if the current user can perform any activity for
* android.intent.action.GET_CONTENT action for images.
*/
static boolean canChoosePhoto(Context context) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
return context.getPackageManager().queryIntentActivities(intent, 0).size() > 0;
}
/**
* Check if the current user can perform any activity for
* com.android.camera.action.CROP action for images.
*/
static boolean canCropPhoto(Context context) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setType("image/*");
return context.getPackageManager().queryIntentActivities(intent, 0).size() > 0;
}
}

View File

@@ -1,208 +0,0 @@
/*
* Copyright (C) 2013 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.app.ActivityManager;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.DialogInterface;
import android.content.Intent;
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;
import com.android.internal.util.UserIcons;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.utils.ThreadUtils;
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;
private View mHeaderView;
private ImageView mUserIconView;
private TextView mUserNameView;
private ImageView mDeleteButton;
private View mSwitchUserView;
private TextView mSwitchTitle;
private EditUserInfoController mEditUserInfoController =
new EditUserInfoController();
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
if (icicle != null) {
mEditUserInfoController.onRestoreInstanceState(icicle);
}
init(icicle);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
mHeaderView = setPinnedHeaderView(R.layout.user_info_header);
mHeaderView.setOnClickListener(this);
mUserIconView = (ImageView) mHeaderView.findViewById(android.R.id.icon);
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);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mEditUserInfoController.onSaveInstanceState(outState);
}
@Override
public void onResume() {
super.onResume();
// Check if user still exists
UserInfo info = Utils.getExistingUser(mUserManager, mUser);
if (info == null) {
finishFragment();
} else {
((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);
}
}
}
@Override
public void startActivityForResult(Intent intent, int requestCode) {
mEditUserInfoController.startingActivityForResult();
super.startActivityForResult(intent, requestCode);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
mEditUserInfoController.onActivityResult(requestCode, resultCode, data);
}
@Override
public void onClick(View view) {
if (view == mHeaderView) {
showDialog(DIALOG_ID_EDIT_USER_INFO);
} else if (view == mDeleteButton) {
showDialog(DIALOG_CONFIRM_REMOVE);
} else {
super.onClick(view); // in AppRestrictionsFragment
}
}
@Override
public Dialog onCreateDialog(int dialogId) {
if (dialogId == DIALOG_ID_EDIT_USER_INFO) {
return mEditUserInfoController.createDialog(this, mUserIconView.getDrawable(),
mUserNameView.getText(), getString(R.string.profile_info_settings_title),
this, mUser, null);
} else if (dialogId == DIALOG_CONFIRM_REMOVE) {
Dialog dlg =
UserDialogs.createRemoveDialog(getActivity(), mUser.getIdentifier(),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
removeUser();
}
}
);
return dlg;
}
return null;
}
@Override
public int getDialogMetricsCategory(int dialogId) {
switch (dialogId) {
case DIALOG_ID_EDIT_USER_INFO:
return SettingsEnums.DIALOG_USER_EDIT;
case DIALOG_CONFIRM_REMOVE:
return SettingsEnums.DIALOG_USER_REMOVE;
default:
return 0;
}
}
private void removeUser() {
getView().post(new Runnable() {
public void run() {
mUserManager.removeUser(mUser.getIdentifier());
finishFragment();
}
});
}
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);
ThreadUtils.postOnBackgroundThread(new Runnable() {
@Override
public void run() {
mUserManager.setUserIcon(user.getIdentifier(), UserIcons.convertToBitmap(photo));
}
});
}
@Override
public void onLabelChanged(UserHandle user, CharSequence label) {
mUserNameView.setText(label);
mUserManager.setUserName(user.getIdentifier(), label.toString());
}
}

View File

@@ -36,6 +36,7 @@ import androidx.preference.SwitchPreference;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment; import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.core.SubSettingLauncher;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -56,6 +57,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
private static final String KEY_SWITCH_USER = "switch_user"; private static final String KEY_SWITCH_USER = "switch_user";
private static final String KEY_ENABLE_TELEPHONY = "enable_calling"; private static final String KEY_ENABLE_TELEPHONY = "enable_calling";
private static final String KEY_REMOVE_USER = "remove_user"; private static final String KEY_REMOVE_USER = "remove_user";
private static final String KEY_APP_AND_CONTENT_ACCESS = "app_and_content_access";
/** Integer extra containing the userId to manage */ /** Integer extra containing the userId to manage */
static final String EXTRA_USER_ID = "user_id"; static final String EXTRA_USER_ID = "user_id";
@@ -69,6 +71,8 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
Preference mSwitchUserPref; Preference mSwitchUserPref;
private SwitchPreference mPhonePref; private SwitchPreference mPhonePref;
@VisibleForTesting @VisibleForTesting
Preference mAppAndContentAccessPref;
@VisibleForTesting
Preference mRemoveUserPref; Preference mRemoveUserPref;
@VisibleForTesting @VisibleForTesting
@@ -109,6 +113,8 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
switchUser(); switchUser();
} }
return true; return true;
} else if (preference == mAppAndContentAccessPref) {
openAppAndContentAccessScreen(false);
} }
return false; return false;
} }
@@ -170,11 +176,14 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
if (userId == USER_NULL) { if (userId == USER_NULL) {
throw new IllegalStateException("Arguments to this fragment must contain the user id"); throw new IllegalStateException("Arguments to this fragment must contain the user id");
} }
boolean isNewUser =
arguments.getBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, false);
mUserInfo = mUserManager.getUserInfo(userId); mUserInfo = mUserManager.getUserInfo(userId);
mSwitchUserPref = findPreference(KEY_SWITCH_USER); mSwitchUserPref = findPreference(KEY_SWITCH_USER);
mPhonePref = findPreference(KEY_ENABLE_TELEPHONY); mPhonePref = findPreference(KEY_ENABLE_TELEPHONY);
mRemoveUserPref = findPreference(KEY_REMOVE_USER); mRemoveUserPref = findPreference(KEY_REMOVE_USER);
mAppAndContentAccessPref = findPreference(KEY_APP_AND_CONTENT_ACCESS);
mSwitchUserPref.setTitle( mSwitchUserPref.setTitle(
context.getString(com.android.settingslib.R.string.user_switch_to_user, context.getString(com.android.settingslib.R.string.user_switch_to_user,
@@ -184,16 +193,24 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
if (!mUserManager.isAdminUser()) { // non admin users can't remove users and allow calls if (!mUserManager.isAdminUser()) { // non admin users can't remove users and allow calls
removePreference(KEY_ENABLE_TELEPHONY); removePreference(KEY_ENABLE_TELEPHONY);
removePreference(KEY_REMOVE_USER); removePreference(KEY_REMOVE_USER);
removePreference(KEY_APP_AND_CONTENT_ACCESS);
} else { } else {
if (!Utils.isVoiceCapable(context)) { // no telephony if (!Utils.isVoiceCapable(context)) { // no telephony
removePreference(KEY_ENABLE_TELEPHONY); removePreference(KEY_ENABLE_TELEPHONY);
} }
if (!mUserInfo.isGuest()) { if (mUserInfo.isRestricted()) {
mPhonePref.setChecked(!mUserManager.hasUserRestriction( removePreference(KEY_ENABLE_TELEPHONY);
UserManager.DISALLOW_OUTGOING_CALLS, new UserHandle(userId))); if (isNewUser) {
mRemoveUserPref.setTitle(R.string.user_remove_user); // for newly created restricted users we should open the apps and content access
// screen to initialize the default restrictions
openAppAndContentAccessScreen(true);
}
} else { } else {
removePreference(KEY_APP_AND_CONTENT_ACCESS);
}
if (mUserInfo.isGuest()) {
// These are not for an existing user, just general Guest settings. // These are not for an existing user, just general Guest settings.
// Default title is for calling and SMS. Change to calling-only here // Default title is for calling and SMS. Change to calling-only here
mPhonePref.setTitle(R.string.user_enable_calling); mPhonePref.setTitle(R.string.user_enable_calling);
@@ -201,6 +218,10 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
mPhonePref.setChecked( mPhonePref.setChecked(
!mDefaultGuestRestrictions.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS)); !mDefaultGuestRestrictions.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS));
mRemoveUserPref.setTitle(R.string.user_exit_guest_title); mRemoveUserPref.setTitle(R.string.user_exit_guest_title);
} else {
mPhonePref.setChecked(!mUserManager.hasUserRestriction(
UserManager.DISALLOW_OUTGOING_CALLS, new UserHandle(userId)));
mRemoveUserPref.setTitle(R.string.user_remove_user);
} }
if (RestrictedLockUtilsInternal.hasBaseUserRestriction(context, if (RestrictedLockUtilsInternal.hasBaseUserRestriction(context,
UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId())) { UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId())) {
@@ -209,6 +230,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
mRemoveUserPref.setOnPreferenceClickListener(this); mRemoveUserPref.setOnPreferenceClickListener(this);
mPhonePref.setOnPreferenceChangeListener(this); mPhonePref.setOnPreferenceChangeListener(this);
mAppAndContentAccessPref.setOnPreferenceClickListener(this);
} }
} }
@@ -283,4 +305,20 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
mUserManager.removeUser(mUserInfo.id); mUserManager.removeUser(mUserInfo.id);
finishFragment(); finishFragment();
} }
/**
* @param isNewUser indicates if a user was created recently, for new users
* AppRestrictionsFragment should set the default restrictions
*/
private void openAppAndContentAccessScreen(boolean isNewUser) {
Bundle extras = new Bundle();
extras.putInt(AppRestrictionsFragment.EXTRA_USER_ID, mUserInfo.id);
extras.putBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, isNewUser);
new SubSettingLauncher(getContext())
.setDestination(AppRestrictionsFragment.class.getName())
.setArguments(extras)
.setTitleRes(R.string.user_restrictions_title)
.setSourceMetricsCategory(getMetricsCategory())
.launch();
}
} }

View File

@@ -485,23 +485,13 @@ public class UserSettings extends SettingsPreferenceFragment
private void onManageUserClicked(int userId, boolean newUser) { private void onManageUserClicked(int userId, boolean newUser) {
mAddingUser = false; mAddingUser = false;
UserInfo userInfo = mUserManager.getUserInfo(userId); UserInfo userInfo = mUserManager.getUserInfo(userId);
if (userInfo.isRestricted() && mUserCaps.mIsAdmin) { if (userId == UserHandle.myUserId()) {
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()) {
// Jump to owner info panel // Jump to owner info panel
OwnerInfoSettings.show(this); OwnerInfoSettings.show(this);
} else { } else {
Bundle extras = new Bundle(); Bundle extras = new Bundle();
extras.putInt(UserDetailsSettings.EXTRA_USER_ID, userId); extras.putInt(UserDetailsSettings.EXTRA_USER_ID, userId);
extras.putBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, newUser);
new SubSettingLauncher(getContext()) new SubSettingLauncher(getContext())
.setDestination(UserDetailsSettings.class.getName()) .setDestination(UserDetailsSettings.class.getName())
.setArguments(extras) .setArguments(extras)
@@ -963,10 +953,10 @@ public class UserSettings extends SettingsPreferenceFragment
pref.setSummary(R.string.user_summary_restricted_not_set_up); pref.setSummary(R.string.user_summary_restricted_not_set_up);
} else { } else {
pref.setSummary(R.string.user_summary_not_set_up); pref.setSummary(R.string.user_summary_not_set_up);
// Disallow setting up user which results in user switching when the
// restriction is set.
pref.setEnabled(!mUserCaps.mDisallowSwitchUser && canSwitchUserNow());
} }
// Disallow setting up user which results in user switching when the restriction is
// set.
pref.setEnabled(!mUserCaps.mDisallowSwitchUser && canSwitchUserNow());
} else if (user.isRestricted()) { } else if (user.isRestricted()) {
pref.setSummary(R.string.user_summary_restricted_profile); pref.setSummary(R.string.user_summary_restricted_profile);
} }
@@ -1137,17 +1127,14 @@ public class UserSettings extends SettingsPreferenceFragment
showDialog(DIALOG_CONFIRM_EXIT_GUEST); showDialog(DIALOG_CONFIRM_EXIT_GUEST);
return true; return true;
} }
// If this is a limited user, launch the user info settings instead of profile editor showDialog(DIALOG_USER_PROFILE_EDITOR);
if (mUserManager.isRestrictedProfile()) {
onManageUserClicked(UserHandle.myUserId(), false);
} else {
showDialog(DIALOG_USER_PROFILE_EDITOR);
}
} else if (pref instanceof UserPreference) { } else if (pref instanceof UserPreference) {
int userId = ((UserPreference) pref).getUserId(); int userId = ((UserPreference) pref).getUserId();
// Get the latest status of the user // Get the latest status of the user
UserInfo user = mUserManager.getUserInfo(userId); UserInfo user = mUserManager.getUserInfo(userId);
if (!user.isInitialized()) { if (!user.isInitialized() && isSecondaryUser(user)) {
// for uninitialized secondary users we should show a prompt dialog before
// starting the setup
mHandler.sendMessage(mHandler.obtainMessage( mHandler.sendMessage(mHandler.obtainMessage(
MESSAGE_SETUP_USER, user.id, user.serialNumber)); MESSAGE_SETUP_USER, user.id, user.serialNumber));
} else { } else {
@@ -1279,4 +1266,7 @@ public class UserSettings extends SettingsPreferenceFragment
} }
}; };
private boolean isSecondaryUser(UserInfo user) {
return UserManager.USER_TYPE_FULL_SECONDARY.equals(user.userType);
}
} }

View File

@@ -28,7 +28,9 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.app.Dialog; import android.app.Dialog;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
@@ -62,6 +64,8 @@ public class EditUserInfoControllerTest {
@Mock @Mock
private Drawable mCurrentIcon; private Drawable mCurrentIcon;
private boolean mCanChangePhoto;
private FragmentActivity mActivity; private FragmentActivity mActivity;
private TestEditUserInfoController mController; private TestEditUserInfoController mController;
@@ -78,6 +82,11 @@ public class EditUserInfoControllerTest {
mPhotoController = mock(EditUserPhotoController.class, Answers.RETURNS_DEEP_STUBS); mPhotoController = mock(EditUserPhotoController.class, Answers.RETURNS_DEEP_STUBS);
return mPhotoController; return mPhotoController;
} }
@Override
boolean canChangePhoto(Context context, UserInfo user) {
return mCanChangePhoto;
}
} }
@Before @Before
@@ -86,6 +95,7 @@ public class EditUserInfoControllerTest {
mActivity = spy(ActivityController.of(new FragmentActivity()).get()); mActivity = spy(ActivityController.of(new FragmentActivity()).get());
when(mFragment.getActivity()).thenReturn(mActivity); when(mFragment.getActivity()).thenReturn(mActivity);
mController = new TestEditUserInfoController(); mController = new TestEditUserInfoController();
mCanChangePhoto = true;
} }
@Test @Test
@@ -256,4 +266,17 @@ public class EditUserInfoControllerTest {
verify(dialogCompleteCallback, times(1)).onPositive(); verify(dialogCompleteCallback, times(1)).onPositive();
verify(dialogCompleteCallback, times(0)).onNegativeOrCancel(); verify(dialogCompleteCallback, times(0)).onNegativeOrCancel();
} }
@Test
public void createDialog_canNotChangePhoto_nullPhotoController() {
mCanChangePhoto = false;
mController.createDialog(
mFragment, mCurrentIcon, "test",
"title", null,
android.os.Process.myUserHandle(),
null);
assertThat(mController.mPhotoController).isNull();
}
} }

View File

@@ -32,9 +32,11 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.robolectric.Shadows.shadowOf;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
@@ -47,6 +49,8 @@ import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference; import androidx.preference.SwitchPreference;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.SubSettings;
import com.android.settings.testutils.shadow.ShadowDevicePolicyManager; import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
import com.android.settings.testutils.shadow.ShadowUserManager; import com.android.settings.testutils.shadow.ShadowUserManager;
@@ -61,6 +65,7 @@ import org.robolectric.RuntimeEnvironment;
import org.robolectric.android.controller.ActivityController; import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow; import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowIntent;
import org.robolectric.util.ReflectionHelpers; import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList; import java.util.ArrayList;
@@ -76,6 +81,7 @@ public class UserDetailsSettingsTest {
private static final String KEY_SWITCH_USER = "switch_user"; private static final String KEY_SWITCH_USER = "switch_user";
private static final String KEY_ENABLE_TELEPHONY = "enable_calling"; private static final String KEY_ENABLE_TELEPHONY = "enable_calling";
private static final String KEY_REMOVE_USER = "remove_user"; private static final String KEY_REMOVE_USER = "remove_user";
private static final String KEY_APP_AND_CONTENT_ACCESS = "app_and_content_access";
private static final int DIALOG_CONFIRM_REMOVE = 1; private static final int DIALOG_CONFIRM_REMOVE = 1;
@@ -90,6 +96,8 @@ public class UserDetailsSettingsTest {
private SwitchPreference mPhonePref; private SwitchPreference mPhonePref;
@Mock @Mock
private Preference mRemoveUserPref; private Preference mRemoveUserPref;
@Mock
private Preference mAppAndContentAccessPref;
private FragmentActivity mActivity; private FragmentActivity mActivity;
private Context mContext; private Context mContext;
@@ -114,14 +122,15 @@ public class UserDetailsSettingsTest {
ReflectionHelpers.setField(mFragment, "mUserManager", userManager); ReflectionHelpers.setField(mFragment, "mUserManager", userManager);
doReturn(mActivity).when(mFragment).getActivity(); doReturn(mActivity).when(mFragment).getActivity();
doReturn(mContext).when(mFragment).getContext(); doReturn(mActivity).when(mFragment).getContext();
doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen(); doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
doReturn("").when(mActivity).getString(anyInt(), anyString());
doReturn(mSwitchUserPref).when(mFragment).findPreference(KEY_SWITCH_USER); doReturn(mSwitchUserPref).when(mFragment).findPreference(KEY_SWITCH_USER);
doReturn(mPhonePref).when(mFragment).findPreference(KEY_ENABLE_TELEPHONY); doReturn(mPhonePref).when(mFragment).findPreference(KEY_ENABLE_TELEPHONY);
doReturn(mRemoveUserPref).when(mFragment).findPreference(KEY_REMOVE_USER); doReturn(mRemoveUserPref).when(mFragment).findPreference(KEY_REMOVE_USER);
doReturn(mAppAndContentAccessPref)
.when(mFragment).findPreference(KEY_APP_AND_CONTENT_ACCESS);
} }
@After @After
@@ -169,6 +178,24 @@ public class UserDetailsSettingsTest {
verify(mFragment, never()).removePreference(KEY_SWITCH_USER); verify(mFragment, never()).removePreference(KEY_SWITCH_USER);
} }
@Test
public void initialize_userSelected_shouldNotShowAppAndContentPref() {
setupSelectedUser();
mFragment.initialize(mActivity, mArguments);
verify(mFragment).removePreference(KEY_APP_AND_CONTENT_ACCESS);
}
@Test
public void initialize_guestSelected_shouldNotShowAppAndContentPref() {
setupSelectedGuest();
mFragment.initialize(mActivity, mArguments);
verify(mFragment).removePreference(KEY_APP_AND_CONTENT_ACCESS);
}
@Test @Test
public void onResume_canSwitch_shouldEnableSwitchPref() { public void onResume_canSwitch_shouldEnableSwitchPref() {
mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_OK); mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_OK);
@@ -248,6 +275,16 @@ public class UserDetailsSettingsTest {
verify(mFragment).removePreference(KEY_ENABLE_TELEPHONY); verify(mFragment).removePreference(KEY_ENABLE_TELEPHONY);
} }
@Test
public void initialize_nonAdmin_shouldNotShowAppAndContentPref() {
setupSelectedUser();
mUserManager.setIsAdminUser(false);
mFragment.initialize(mActivity, mArguments);
verify(mFragment).removePreference(KEY_APP_AND_CONTENT_ACCESS);
}
@Test @Test
public void initialize_adminSelectsSecondaryUser_shouldShowRemovePreference() { public void initialize_adminSelectsSecondaryUser_shouldShowRemovePreference() {
setupSelectedUser(); setupSelectedUser();
@@ -260,6 +297,57 @@ public class UserDetailsSettingsTest {
verify(mFragment, never()).removePreference(KEY_REMOVE_USER); verify(mFragment, never()).removePreference(KEY_REMOVE_USER);
} }
@Test
public void initialize_adminSelectsNewRestrictedUser_shouldOpenAppContentScreen() {
setupSelectedRestrictedUser();
mUserManager.setIsAdminUser(true);
mArguments.putBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, true);
mFragment.initialize(mActivity, mArguments);
Intent startedIntent = shadowOf(mActivity).getNextStartedActivity();
ShadowIntent shadowIntent = shadowOf(startedIntent);
assertThat(shadowIntent.getIntentClass()).isEqualTo(SubSettings.class);
assertThat(startedIntent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
.isEqualTo(AppRestrictionsFragment.class.getName());
Bundle arguments = startedIntent.getBundleExtra(
SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS);
assertThat(arguments).isNotNull();
assertThat(arguments.getInt(AppRestrictionsFragment.EXTRA_USER_ID, 0))
.isEqualTo(mUserInfo.id);
assertThat(arguments.getBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, false))
.isEqualTo(true);
}
@Test
public void initialize_adminSelectsRestrictedUser_shouldSetupPreferences() {
setupSelectedRestrictedUser();
mUserManager.setIsAdminUser(true);
doReturn(true).when(mTelephonyManager).isVoiceCapable();
mFragment.initialize(mActivity, mArguments);
verify(mFragment, never()).removePreference(KEY_REMOVE_USER);
verify(mFragment, never()).removePreference(KEY_SWITCH_USER);
verify(mFragment, never()).removePreference(KEY_APP_AND_CONTENT_ACCESS);
verify(mFragment).removePreference(KEY_ENABLE_TELEPHONY);
verify(mSwitchUserPref).setTitle("Switch to " + mUserInfo.name);
verify(mAppAndContentAccessPref).setOnPreferenceClickListener(mFragment);
verify(mSwitchUserPref).setOnPreferenceClickListener(mFragment);
verify(mRemoveUserPref).setOnPreferenceClickListener(mFragment);
}
@Test
public void initialize_adminSelectsExistingRestrictedUser_shouldNotStartAppAndContentAccess() {
setupSelectedRestrictedUser();
mUserManager.setIsAdminUser(true);
mArguments.putBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, false);
mFragment.initialize(mActivity, mArguments);
verify(mActivity, never()).startActivity(any(Intent.class));
}
@Test @Test
public void initialize_adminSelectsGuest_shouldShowRemovePreference() { public void initialize_adminSelectsGuest_shouldShowRemovePreference() {
setupSelectedGuest(); setupSelectedGuest();
@@ -344,6 +432,7 @@ public class UserDetailsSettingsTest {
mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_OK); mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_OK);
mFragment.mSwitchUserPref = mSwitchUserPref; mFragment.mSwitchUserPref = mSwitchUserPref;
mFragment.mRemoveUserPref = mRemoveUserPref; mFragment.mRemoveUserPref = mRemoveUserPref;
mFragment.mAppAndContentAccessPref = mAppAndContentAccessPref;
mFragment.mUserInfo = mUserInfo; mFragment.mUserInfo = mUserInfo;
mFragment.onPreferenceClick(mSwitchUserPref); mFragment.onPreferenceClick(mSwitchUserPref);
@@ -357,6 +446,7 @@ public class UserDetailsSettingsTest {
mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED); mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED);
mFragment.mSwitchUserPref = mSwitchUserPref; mFragment.mSwitchUserPref = mSwitchUserPref;
mFragment.mRemoveUserPref = mRemoveUserPref; mFragment.mRemoveUserPref = mRemoveUserPref;
mFragment.mAppAndContentAccessPref = mAppAndContentAccessPref;
mFragment.mUserInfo = mUserInfo; mFragment.mUserInfo = mUserInfo;
mFragment.onPreferenceClick(mSwitchUserPref); mFragment.onPreferenceClick(mSwitchUserPref);
@@ -371,6 +461,7 @@ public class UserDetailsSettingsTest {
mUserManager.setIsAdminUser(true); mUserManager.setIsAdminUser(true);
mFragment.mSwitchUserPref = mSwitchUserPref; mFragment.mSwitchUserPref = mSwitchUserPref;
mFragment.mRemoveUserPref = mRemoveUserPref; mFragment.mRemoveUserPref = mRemoveUserPref;
mFragment.mAppAndContentAccessPref = mAppAndContentAccessPref;
doNothing().when(mFragment).showDialog(anyInt()); doNothing().when(mFragment).showDialog(anyInt());
mFragment.onPreferenceClick(mRemoveUserPref); mFragment.onPreferenceClick(mRemoveUserPref);
@@ -386,6 +477,7 @@ public class UserDetailsSettingsTest {
mUserManager.setIsAdminUser(false); mUserManager.setIsAdminUser(false);
mFragment.mSwitchUserPref = mSwitchUserPref; mFragment.mSwitchUserPref = mSwitchUserPref;
mFragment.mRemoveUserPref = mRemoveUserPref; mFragment.mRemoveUserPref = mRemoveUserPref;
mFragment.mAppAndContentAccessPref = mAppAndContentAccessPref;
doNothing().when(mFragment).showDialog(anyInt()); doNothing().when(mFragment).showDialog(anyInt());
mFragment.onPreferenceClick(mRemoveUserPref); mFragment.onPreferenceClick(mRemoveUserPref);
@@ -394,12 +486,37 @@ public class UserDetailsSettingsTest {
verify(mFragment, never()).showDialog(DIALOG_CONFIRM_REMOVE); verify(mFragment, never()).showDialog(DIALOG_CONFIRM_REMOVE);
} }
@Test
public void onPreferenceClick_selectRestrictedUser_appAndContentAccessClicked_startActivity() {
setupSelectedRestrictedUser();
mFragment.mUserInfo = mUserInfo;
mUserManager.setIsAdminUser(true);
mFragment.mSwitchUserPref = mSwitchUserPref;
mFragment.mRemoveUserPref = mRemoveUserPref;
mFragment.mAppAndContentAccessPref = mAppAndContentAccessPref;
mFragment.onPreferenceClick(mAppAndContentAccessPref);
Intent startedIntent = shadowOf(mActivity).getNextStartedActivity();
ShadowIntent shadowIntent = shadowOf(startedIntent);
assertThat(shadowIntent.getIntentClass()).isEqualTo(SubSettings.class);
assertThat(startedIntent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
.isEqualTo(AppRestrictionsFragment.class.getName());
Bundle arguments = startedIntent.getBundleExtra(
SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS);
assertThat(arguments.getInt(AppRestrictionsFragment.EXTRA_USER_ID, 0))
.isEqualTo(mUserInfo.id);
assertThat(arguments.getBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, true))
.isEqualTo(false);
}
@Test @Test
public void onPreferenceClick_unknownPreferenceClicked_doNothing() { public void onPreferenceClick_unknownPreferenceClicked_doNothing() {
setupSelectedUser(); setupSelectedUser();
mFragment.mUserInfo = mUserInfo; mFragment.mUserInfo = mUserInfo;
mFragment.mSwitchUserPref = mSwitchUserPref; mFragment.mSwitchUserPref = mSwitchUserPref;
mFragment.mRemoveUserPref = mRemoveUserPref; mFragment.mRemoveUserPref = mRemoveUserPref;
mFragment.mAppAndContentAccessPref = mAppAndContentAccessPref;
mFragment.onPreferenceClick(mock(UserPreference.class)); mFragment.onPreferenceClick(mock(UserPreference.class));
@@ -464,4 +581,13 @@ public class UserDetailsSettingsTest {
mUserManager.addProfile(mUserInfo); mUserManager.addProfile(mUserInfo);
} }
private void setupSelectedRestrictedUser() {
mArguments.putInt("user_id", 21);
mUserInfo = new UserInfo(21, "Bob", null,
UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_RESTRICTED,
UserManager.USER_TYPE_FULL_RESTRICTED);
mUserManager.addProfile(mUserInfo);
}
} }