Revert "Improve multi user settings screen"
This reverts commit d19dc306dd
.
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
This commit is contained in:
@@ -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>
|
|
||||||
|
|
@@ -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>
|
|
@@ -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>
|
|
60
res/layout/restricted_preference_user_delete_widget.xml
Normal file
60
res/layout/restricted_preference_user_delete_widget.xml
Normal file
@@ -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>
|
@@ -15,7 +15,6 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
@@ -46,7 +45,8 @@
|
|||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:minWidth="48dp"
|
android:minWidth="48dp"
|
||||||
android:scaleType="centerInside"
|
android:scaleType="centerInside"
|
||||||
android:layout_marginEnd="@*android:dimen/preference_item_padding_inner"/>
|
android:layout_marginEnd="@*android:dimen/preference_item_padding_inner"
|
||||||
|
/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -60,7 +60,6 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
tools:text="Richard"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:ellipsize="marquee"
|
android:ellipsize="marquee"
|
||||||
android:fadingEdge="horizontal"/>
|
android:fadingEdge="horizontal"/>
|
||||||
@@ -89,40 +88,6 @@
|
|||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:background="?android:attr/selectableItemBackground" />
|
android:background="?android:attr/selectableItemBackground" />
|
||||||
</LinearLayout>
|
</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"
|
<View android:layout_width="match_parent"
|
||||||
android:layout_height="2dp"
|
android:layout_height="2dp"
|
||||||
android:background="@color/divider_color" />
|
android:background="@color/divider_color" />
|
||||||
|
@@ -17,17 +17,12 @@
|
|||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:settings="http://schemas.android.com/apk/res-auto">
|
xmlns:settings="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
|
||||||
<com.android.settingslib.RestrictedPreference
|
|
||||||
android:key="switch_user"
|
|
||||||
android:icon="@drawable/ic_swap" />
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:key="enable_calling"
|
android:key="enable_calling"
|
||||||
android:icon="@drawable/ic_phone"
|
|
||||||
android:title="@string/user_enable_calling_sms" />
|
android:title="@string/user_enable_calling_sms" />
|
||||||
<com.android.settingslib.RestrictedPreference
|
<com.android.settingslib.RestrictedPreference
|
||||||
android:key="remove_user"
|
android:key="remove_user"
|
||||||
android:icon="@drawable/ic_delete"
|
android:title="@string/user_remove_user"
|
||||||
settings:userRestriction="no_remove_user"
|
settings:userRestriction="no_remove_user"
|
||||||
settings:useAdminDisabledSummary="true" />
|
settings:useAdminDisabledSummary="true" />
|
||||||
|
|
||||||
|
@@ -27,15 +27,10 @@
|
|||||||
settings:searchable="false">
|
settings:searchable="false">
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<com.android.settingslib.RestrictedPreference
|
|
||||||
android:key="guest_add"
|
|
||||||
android:title="@string/guest_new_guest"
|
|
||||||
android:order="15"/>
|
|
||||||
|
|
||||||
<com.android.settingslib.RestrictedPreference
|
<com.android.settingslib.RestrictedPreference
|
||||||
android:key="user_add"
|
android:key="user_add"
|
||||||
android:title="@string/user_add_user_or_profile_menu"
|
android:title="@string/user_add_user_or_profile_menu"
|
||||||
android:icon="@drawable/ic_add_40dp"
|
android:icon="@drawable/ic_add_24dp"
|
||||||
android:order="20"/>
|
android:order="20"/>
|
||||||
|
|
||||||
<com.android.settingslib.RestrictedSwitchPreference
|
<com.android.settingslib.RestrictedSwitchPreference
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
@@ -226,7 +219,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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.android.settings.users;
|
package com.android.settings.users;
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.settings.SettingsEnums;
|
import android.app.settings.SettingsEnums;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
@@ -24,10 +23,7 @@ import android.content.Intent;
|
|||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.RemoteException;
|
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
@@ -40,7 +36,6 @@ import com.android.settingslib.utils.ThreadUtils;
|
|||||||
public class RestrictedProfileSettings extends AppRestrictionsFragment
|
public class RestrictedProfileSettings extends AppRestrictionsFragment
|
||||||
implements EditUserInfoController.OnContentChangedCallback {
|
implements EditUserInfoController.OnContentChangedCallback {
|
||||||
|
|
||||||
private static final String TAG = RestrictedProfileSettings.class.getSimpleName();
|
|
||||||
public static final String FILE_PROVIDER_AUTHORITY = "com.android.settings.files";
|
public static final String FILE_PROVIDER_AUTHORITY = "com.android.settings.files";
|
||||||
static final int DIALOG_ID_EDIT_USER_INFO = 1;
|
static final int DIALOG_ID_EDIT_USER_INFO = 1;
|
||||||
private static final int DIALOG_CONFIRM_REMOVE = 2;
|
private static final int DIALOG_CONFIRM_REMOVE = 2;
|
||||||
@@ -49,8 +44,6 @@ public class RestrictedProfileSettings extends AppRestrictionsFragment
|
|||||||
private ImageView mUserIconView;
|
private ImageView mUserIconView;
|
||||||
private TextView mUserNameView;
|
private TextView mUserNameView;
|
||||||
private ImageView mDeleteButton;
|
private ImageView mDeleteButton;
|
||||||
private View mSwitchUserView;
|
|
||||||
private TextView mSwitchTitle;
|
|
||||||
|
|
||||||
private EditUserInfoController mEditUserInfoController =
|
private EditUserInfoController mEditUserInfoController =
|
||||||
new EditUserInfoController();
|
new EditUserInfoController();
|
||||||
@@ -74,11 +67,6 @@ public class RestrictedProfileSettings extends AppRestrictionsFragment
|
|||||||
mUserNameView = (TextView) mHeaderView.findViewById(android.R.id.title);
|
mUserNameView = (TextView) mHeaderView.findViewById(android.R.id.title);
|
||||||
mDeleteButton = (ImageView) mHeaderView.findViewById(R.id.delete);
|
mDeleteButton = (ImageView) mHeaderView.findViewById(R.id.delete);
|
||||||
mDeleteButton.setOnClickListener(this);
|
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.
|
// This is going to bind the preferences.
|
||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
}
|
}
|
||||||
@@ -92,6 +80,7 @@ public class RestrictedProfileSettings extends AppRestrictionsFragment
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
// Check if user still exists
|
// Check if user still exists
|
||||||
UserInfo info = Utils.getExistingUser(mUserManager, mUser);
|
UserInfo info = Utils.getExistingUser(mUserManager, mUser);
|
||||||
if (info == null) {
|
if (info == null) {
|
||||||
@@ -100,16 +89,6 @@ public class RestrictedProfileSettings extends AppRestrictionsFragment
|
|||||||
((TextView) mHeaderView.findViewById(android.R.id.title)).setText(info.name);
|
((TextView) mHeaderView.findViewById(android.R.id.title)).setText(info.name);
|
||||||
((ImageView) mHeaderView.findViewById(android.R.id.icon)).setImageDrawable(
|
((ImageView) mHeaderView.findViewById(android.R.id.icon)).setImageDrawable(
|
||||||
com.android.settingslib.Utils.getUserIcon(getActivity(), mUserManager, info));
|
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 @@ public class RestrictedProfileSettings extends AppRestrictionsFragment
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void switchUser() {
|
|
||||||
try {
|
|
||||||
ActivityManager.getService().switchUser(mUser.getIdentifier());
|
|
||||||
} catch (RemoteException re) {
|
|
||||||
Log.e(TAG, "Error while switching to other user.");
|
|
||||||
} finally {
|
|
||||||
finishFragment();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPhotoChanged(UserHandle user, Drawable photo) {
|
public void onPhotoChanged(UserHandle user, Drawable photo) {
|
||||||
mUserIconView.setImageDrawable(photo);
|
mUserIconView.setImageDrawable(photo);
|
||||||
|
@@ -16,63 +16,55 @@
|
|||||||
|
|
||||||
package com.android.settings.users;
|
package com.android.settings.users;
|
||||||
|
|
||||||
import static android.os.UserHandle.USER_NULL;
|
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.settings.SettingsEnums;
|
import android.app.settings.SettingsEnums;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.RemoteException;
|
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.SwitchPreference;
|
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.settingslib.RestrictedLockUtils;
|
|
||||||
import com.android.settingslib.RestrictedLockUtilsInternal;
|
import com.android.settingslib.RestrictedLockUtilsInternal;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Settings screen for configuring, deleting or switching to a specific user.
|
* Settings screen for configuring a specific user. It can contain user restrictions
|
||||||
* It is shown when you tap on a user in the user management (UserSettings) screen.
|
* 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
|
* 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
|
public class UserDetailsSettings extends SettingsPreferenceFragment
|
||||||
implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener {
|
implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener {
|
||||||
|
|
||||||
private static final String TAG = UserDetailsSettings.class.getSimpleName();
|
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_ENABLE_TELEPHONY = "enable_calling";
|
||||||
private static final String KEY_REMOVE_USER = "remove_user";
|
private static final String KEY_REMOVE_USER = "remove_user";
|
||||||
|
|
||||||
/** 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";
|
||||||
|
/** 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_REMOVE = 1;
|
||||||
private static final int DIALOG_CONFIRM_ENABLE_CALLING = 2;
|
private static final int DIALOG_CONFIRM_ENABLE_CALLING = 2;
|
||||||
private static final int DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS = 3;
|
private static final int DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS = 3;
|
||||||
|
|
||||||
private UserManager mUserManager;
|
private UserManager mUserManager;
|
||||||
@VisibleForTesting
|
|
||||||
Preference mSwitchUserPref;
|
|
||||||
private SwitchPreference mPhonePref;
|
private SwitchPreference mPhonePref;
|
||||||
@VisibleForTesting
|
private Preference mRemoveUserPref;
|
||||||
Preference mRemoveUserPref;
|
|
||||||
|
|
||||||
@VisibleForTesting
|
private UserInfo mUserInfo;
|
||||||
UserInfo mUserInfo;
|
private boolean mGuestUser;
|
||||||
private Bundle mDefaultGuestRestrictions;
|
private Bundle mDefaultGuestRestrictions;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -86,28 +78,46 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
|
|||||||
|
|
||||||
final Context context = getActivity();
|
final Context context = getActivity();
|
||||||
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||||
|
|
||||||
addPreferencesFromResource(R.xml.user_details_settings);
|
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
|
if (!mGuestUser) {
|
||||||
public void onResume() {
|
// Regular user. Get the user id from the caller.
|
||||||
super.onResume();
|
final int userId = getArguments().getInt(EXTRA_USER_ID, -1);
|
||||||
mSwitchUserPref.setEnabled(canSwitchUserNow());
|
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
|
@Override
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
if (preference == mRemoveUserPref) {
|
if (preference == mRemoveUserPref) {
|
||||||
if (canDeleteUser()) {
|
if (!mUserManager.isAdminUser()) {
|
||||||
showDialog(DIALOG_CONFIRM_REMOVE);
|
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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -116,7 +126,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
|
|||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
if (Boolean.TRUE.equals(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);
|
: DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -124,135 +134,9 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
void enableCallsAndSms(boolean enabled) {
|
||||||
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) {
|
|
||||||
mPhonePref.setChecked(enabled);
|
mPhonePref.setChecked(enabled);
|
||||||
if (mUserInfo.isGuest()) {
|
if (mGuestUser) {
|
||||||
mDefaultGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, !enabled);
|
mDefaultGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, !enabled);
|
||||||
// SMS is always disabled for guest
|
// SMS is always disabled for guest
|
||||||
mDefaultGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true);
|
mDefaultGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true);
|
||||||
@@ -262,7 +146,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
|
|||||||
// TODO: Maybe setDefaultGuestRestrictions() can internally just set the restrictions
|
// TODO: Maybe setDefaultGuestRestrictions() can internally just set the restrictions
|
||||||
// on any existing guest rather than do it here with multiple Binder calls.
|
// on any existing guest rather than do it here with multiple Binder calls.
|
||||||
List<UserInfo> users = mUserManager.getUsers(true);
|
List<UserInfo> users = mUserManager.getUsers(true);
|
||||||
for (UserInfo user : users) {
|
for (UserInfo user: users) {
|
||||||
if (user.isGuest()) {
|
if (user.isGuest()) {
|
||||||
UserHandle userHandle = UserHandle.of(user.id);
|
UserHandle userHandle = UserHandle.of(user.id);
|
||||||
for (String key : mDefaultGuestRestrictions.keySet()) {
|
for (String key : mDefaultGuestRestrictions.keySet()) {
|
||||||
@@ -279,7 +163,51 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
mUserManager.removeUser(mUserInfo.id);
|
||||||
finishFragment();
|
finishFragment();
|
||||||
}
|
}
|
||||||
|
@@ -21,16 +21,18 @@ import android.graphics.drawable.Drawable;
|
|||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import androidx.preference.PreferenceViewHolder;
|
import androidx.preference.PreferenceViewHolder;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settingslib.RestrictedLockUtilsInternal;
|
||||||
import com.android.settingslib.RestrictedPreference;
|
import com.android.settingslib.RestrictedPreference;
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
/**
|
|
||||||
* Preference for a user that appear on {@link UserSettings} screen.
|
|
||||||
*/
|
|
||||||
public class UserPreference extends RestrictedPreference {
|
public class UserPreference extends RestrictedPreference {
|
||||||
private static final int ALPHA_ENABLED = 255;
|
private static final int ALPHA_ENABLED = 255;
|
||||||
private static final int ALPHA_DISABLED = 102;
|
private static final int ALPHA_DISABLED = 102;
|
||||||
@@ -42,7 +44,8 @@ public class UserPreference extends RestrictedPreference {
|
|||||||
|
|
||||||
if (p1 == null) {
|
if (p1 == null) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (p2 == null) {
|
}
|
||||||
|
else if (p2 == null) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int sn1 = p1.getSerialNumber();
|
int sn1 = p1.getSerialNumber();
|
||||||
@@ -55,15 +58,26 @@ public class UserPreference extends RestrictedPreference {
|
|||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private OnClickListener mDeleteClickListener;
|
||||||
|
private OnClickListener mSettingsClickListener;
|
||||||
private int mSerialNumber = -1;
|
private int mSerialNumber = -1;
|
||||||
private int mUserId = USERID_UNKNOWN;
|
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) {
|
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);
|
super(context, attrs);
|
||||||
|
if (deleteListener != null || settingsListener != null) {
|
||||||
|
setWidgetLayoutResource(R.layout.restricted_preference_user_delete_widget);
|
||||||
|
}
|
||||||
|
mDeleteClickListener = deleteListener;
|
||||||
|
mSettingsClickListener = settingsListener;
|
||||||
mUserId = userId;
|
mUserId = userId;
|
||||||
useAdminDisabledSummary(true);
|
useAdminDisabledSummary(true);
|
||||||
}
|
}
|
||||||
@@ -78,13 +92,62 @@ public class UserPreference extends RestrictedPreference {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean shouldHideSecondTarget() {
|
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
|
@Override
|
||||||
public void onBindViewHolder(PreferenceViewHolder view) {
|
public void onBindViewHolder(PreferenceViewHolder view) {
|
||||||
super.onBindViewHolder(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() {
|
private int getSerialNumber() {
|
||||||
|
@@ -48,6 +48,7 @@ import android.util.SparseArray;
|
|||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
import android.widget.SimpleAdapter;
|
import android.widget.SimpleAdapter;
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
@@ -68,6 +69,7 @@ import com.android.settings.password.ChooseLockGeneric;
|
|||||||
import com.android.settings.search.BaseSearchIndexProvider;
|
import com.android.settings.search.BaseSearchIndexProvider;
|
||||||
import com.android.settings.widget.SwitchBar;
|
import com.android.settings.widget.SwitchBar;
|
||||||
import com.android.settings.widget.SwitchBarController;
|
import com.android.settings.widget.SwitchBarController;
|
||||||
|
import com.android.settingslib.RestrictedLockUtils;
|
||||||
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||||
import com.android.settingslib.RestrictedLockUtilsInternal;
|
import com.android.settingslib.RestrictedLockUtilsInternal;
|
||||||
import com.android.settingslib.RestrictedPreference;
|
import com.android.settingslib.RestrictedPreference;
|
||||||
@@ -87,14 +89,15 @@ import java.util.Random;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Screen that manages the list of users on the device.
|
* 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.
|
* Owner is the primary user.
|
||||||
*/
|
*/
|
||||||
@SearchIndexable
|
@SearchIndexable
|
||||||
public class UserSettings extends SettingsPreferenceFragment
|
public class UserSettings extends SettingsPreferenceFragment
|
||||||
implements Preference.OnPreferenceClickListener,
|
implements Preference.OnPreferenceClickListener, View.OnClickListener,
|
||||||
MultiUserSwitchBarController.OnMultiUserSwitchChangedListener,
|
MultiUserSwitchBarController.OnMultiUserSwitchChangedListener,
|
||||||
DialogInterface.OnDismissListener {
|
DialogInterface.OnDismissListener {
|
||||||
|
|
||||||
@@ -108,7 +111,6 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
private static final String KEY_USER_LIST = "user_list";
|
private static final String KEY_USER_LIST = "user_list";
|
||||||
private static final String KEY_USER_ME = "user_me";
|
private static final String KEY_USER_ME = "user_me";
|
||||||
private static final String KEY_USER_GUEST = "user_guest";
|
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 = "user_add";
|
||||||
private static final String KEY_ADD_USER_WHEN_LOCKED = "user_settings_add_users_when_locked";
|
private static final String KEY_ADD_USER_WHEN_LOCKED = "user_settings_add_users_when_locked";
|
||||||
private static final String KEY_MULTIUSER_FOOTER = "multiuser_footer";
|
private static final String KEY_MULTIUSER_FOOTER = "multiuser_footer";
|
||||||
@@ -154,11 +156,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
UserPreference mMePreference;
|
UserPreference mMePreference;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
RestrictedPreference mAddGuest;
|
|
||||||
@VisibleForTesting
|
|
||||||
RestrictedPreference mAddUser;
|
RestrictedPreference mAddUser;
|
||||||
@VisibleForTesting
|
|
||||||
SparseArray<Bitmap> mUserIcons = new SparseArray<>();
|
|
||||||
private int mRemovingUserId = -1;
|
private int mRemovingUserId = -1;
|
||||||
private int mAddedUserId = 0;
|
private int mAddedUserId = 0;
|
||||||
private boolean mAddingUser;
|
private boolean mAddingUser;
|
||||||
@@ -167,6 +165,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
private boolean mShouldUpdateUserList = true;
|
private boolean mShouldUpdateUserList = true;
|
||||||
private final Object mUserLock = new Object();
|
private final Object mUserLock = new Object();
|
||||||
private UserManager mUserManager;
|
private UserManager mUserManager;
|
||||||
|
private SparseArray<Bitmap> mUserIcons = new SparseArray<>();
|
||||||
private static SparseArray<Bitmap> sDarkDefaultUserBitmapCache = new SparseArray<>();
|
private static SparseArray<Bitmap> sDarkDefaultUserBitmapCache = new SparseArray<>();
|
||||||
|
|
||||||
private MultiUserSwitchBarController mSwitchBarController;
|
private MultiUserSwitchBarController mSwitchBarController;
|
||||||
@@ -272,17 +271,15 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
final int myUserId = UserHandle.myUserId();
|
final int myUserId = UserHandle.myUserId();
|
||||||
|
|
||||||
mUserListCategory = (PreferenceGroup) findPreference(KEY_USER_LIST);
|
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.setKey(KEY_USER_ME);
|
||||||
mMePreference.setOnPreferenceClickListener(this);
|
mMePreference.setOnPreferenceClickListener(this);
|
||||||
if (mUserCaps.mIsAdmin) {
|
if (mUserCaps.mIsAdmin) {
|
||||||
mMePreference.setSummary(R.string.user_admin);
|
mMePreference.setSummary(R.string.user_admin);
|
||||||
}
|
}
|
||||||
|
mAddUser = (RestrictedPreference) findPreference(KEY_ADD_USER);
|
||||||
mAddGuest = findPreference(KEY_ADD_GUEST);
|
|
||||||
mAddGuest.setOnPreferenceClickListener(this);
|
|
||||||
|
|
||||||
mAddUser = findPreference(KEY_ADD_USER);
|
|
||||||
if (!mUserCaps.mCanAddRestrictedProfile) {
|
if (!mUserCaps.mCanAddRestrictedProfile) {
|
||||||
// Label should only mention adding a "user", not a "profile"
|
// Label should only mention adding a "user", not a "profile"
|
||||||
mAddUser.setTitle(R.string.user_add_user_menu);
|
mAddUser.setTitle(R.string.user_add_user_menu);
|
||||||
@@ -347,7 +344,8 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
if (!mUserCaps.mIsAdmin && canSwitchUserNow()) {
|
final boolean canSwitchUsers = mUserManager.canSwitchUsers();
|
||||||
|
if (!mUserCaps.mIsAdmin && canSwitchUsers) {
|
||||||
String nickname = mUserManager.getUserName();
|
String nickname = mUserManager.getUserName();
|
||||||
MenuItem removeThisUser = menu.add(0, MENU_REMOVE_USER, pos++,
|
MenuItem removeThisUser = menu.add(0, MENU_REMOVE_USER, pos++,
|
||||||
getResources().getString(R.string.user_remove_user_menu, nickname));
|
getResources().getString(R.string.user_remove_user_menu, nickname));
|
||||||
@@ -388,13 +386,10 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
* Loads profile information for the current user.
|
* Loads profile information for the current user.
|
||||||
*/
|
*/
|
||||||
private void loadProfile() {
|
private void loadProfile() {
|
||||||
if (isCurrentUserGuest()) {
|
if (mUserCaps.mIsGuest) {
|
||||||
// No need to load profile information
|
// No need to load profile information
|
||||||
mMePreference.setIcon(getEncircledDefaultIcon());
|
mMePreference.setIcon(getEncircledDefaultIcon());
|
||||||
mMePreference.setTitle(R.string.user_exit_guest_title);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,9 +412,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void finishLoadProfile(String profileName) {
|
private void finishLoadProfile(String profileName) {
|
||||||
if (getActivity() == null) {
|
if (getActivity() == null) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
mMePreference.setTitle(getString(R.string.user_you, profileName));
|
mMePreference.setTitle(getString(R.string.user_you, profileName));
|
||||||
int myUserId = UserHandle.myUserId();
|
int myUserId = UserHandle.myUserId();
|
||||||
Bitmap b = mUserManager.getUserIcon(myUserId);
|
Bitmap b = mUserManager.getUserIcon(myUserId);
|
||||||
@@ -484,28 +477,38 @@ 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);
|
if (userId == UserPreference.USERID_GUEST_DEFAULTS) {
|
||||||
if (userInfo.isRestricted() && mUserCaps.mIsAdmin) {
|
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();
|
Bundle extras = new Bundle();
|
||||||
extras.putInt(RestrictedProfileSettings.EXTRA_USER_ID, userId);
|
extras.putInt(RestrictedProfileSettings.EXTRA_USER_ID, userId);
|
||||||
extras.putBoolean(RestrictedProfileSettings.EXTRA_NEW_USER, newUser);
|
extras.putBoolean(RestrictedProfileSettings.EXTRA_NEW_USER, newUser);
|
||||||
extras.putBoolean(RestrictedProfileSettings.EXTRA_SHOW_SWITCH_USER, canSwitchUserNow());
|
|
||||||
new SubSettingLauncher(getContext())
|
new SubSettingLauncher(getContext())
|
||||||
.setDestination(RestrictedProfileSettings.class.getName())
|
.setDestination(RestrictedProfileSettings.class.getName())
|
||||||
.setArguments(extras)
|
.setArguments(extras)
|
||||||
.setTitleRes(R.string.user_restrictions_title)
|
.setTitleRes(R.string.user_restrictions_title)
|
||||||
.setSourceMetricsCategory(getMetricsCategory())
|
.setSourceMetricsCategory(getMetricsCategory())
|
||||||
.launch();
|
.launch();
|
||||||
} else if (userId == UserHandle.myUserId()) {
|
} else if (info.id == UserHandle.myUserId()) {
|
||||||
// Jump to owner info panel
|
// Jump to owner info panel
|
||||||
OwnerInfoSettings.show(this);
|
OwnerInfoSettings.show(this);
|
||||||
} else {
|
} else if (mUserCaps.mIsAdmin) {
|
||||||
Bundle extras = new Bundle();
|
final Bundle extras = new Bundle();
|
||||||
extras.putInt(UserDetailsSettings.EXTRA_USER_ID, userId);
|
extras.putInt(UserDetailsSettings.EXTRA_USER_ID, userId);
|
||||||
new SubSettingLauncher(getContext())
|
new SubSettingLauncher(getContext())
|
||||||
.setDestination(UserDetailsSettings.class.getName())
|
.setDestination(UserDetailsSettings.class.getName())
|
||||||
.setArguments(extras)
|
.setArguments(extras)
|
||||||
.setTitleText(userInfo.name)
|
.setTitleText(info.name)
|
||||||
.setSourceMetricsCategory(getMetricsCategory())
|
.setSourceMetricsCategory(getMetricsCategory())
|
||||||
.launch();
|
.launch();
|
||||||
}
|
}
|
||||||
@@ -535,9 +538,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(int dialogId) {
|
public Dialog onCreateDialog(int dialogId) {
|
||||||
Context context = getActivity();
|
Context context = getActivity();
|
||||||
if (context == null) {
|
if (context == null) return null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
switch (dialogId) {
|
switch (dialogId) {
|
||||||
case DIALOG_CONFIRM_REMOVE: {
|
case DIALOG_CONFIRM_REMOVE: {
|
||||||
Dialog dlg =
|
Dialog dlg =
|
||||||
@@ -810,7 +811,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void removeThisUser() {
|
private void removeThisUser() {
|
||||||
if (!canSwitchUserNow()) {
|
if (!mUserManager.canSwitchUsers()) {
|
||||||
Log.w(TAG, "Cannot remove current user when switching is disabled");
|
Log.w(TAG, "Cannot remove current user when switching is disabled");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -881,14 +882,10 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void switchUserNow(int userId) {
|
private void switchUserNow(int userId) {
|
||||||
if (!canSwitchUserNow()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ActivityManager.getService().switchUser(userId);
|
ActivityManager.getService().switchUser(userId);
|
||||||
} catch (RemoteException re) {
|
} catch (RemoteException re) {
|
||||||
Log.e(TAG, "Error while switching to other user.");
|
// Nothing to do
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -897,7 +894,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
*/
|
*/
|
||||||
private void exitGuest() {
|
private void exitGuest() {
|
||||||
// Just to be safe
|
// Just to be safe
|
||||||
if (!isCurrentUserGuest()) {
|
if (!mUserCaps.mIsGuest) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
removeThisUser();
|
removeThisUser();
|
||||||
@@ -911,12 +908,12 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
}
|
}
|
||||||
final List<UserInfo> users = mUserManager.getUsers(true);
|
final List<UserInfo> users = mUserManager.getUsers(true);
|
||||||
|
|
||||||
|
final boolean voiceCapable = Utils.isVoiceCapable(context);
|
||||||
final ArrayList<Integer> missingIcons = new ArrayList<>();
|
final ArrayList<Integer> missingIcons = new ArrayList<>();
|
||||||
final ArrayList<UserPreference> userPreferences = new ArrayList<>();
|
final ArrayList<UserPreference> userPreferences = new ArrayList<>();
|
||||||
|
int guestId = UserPreference.USERID_GUEST_DEFAULTS;
|
||||||
userPreferences.add(mMePreference);
|
userPreferences.add(mMePreference);
|
||||||
|
|
||||||
boolean canOpenUserDetails =
|
|
||||||
mUserCaps.mIsAdmin || (canSwitchUserNow() && !mUserCaps.mDisallowSwitchUser);
|
|
||||||
for (UserInfo user : users) {
|
for (UserInfo user : users) {
|
||||||
if (!user.supportsSwitchToByUser()) {
|
if (!user.supportsSwitchToByUser()) {
|
||||||
// Only users that can be switched to should show up here.
|
// Only users that can be switched to should show up here.
|
||||||
@@ -927,38 +924,37 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
if (user.id == UserHandle.myUserId()) {
|
if (user.id == UserHandle.myUserId()) {
|
||||||
pref = mMePreference;
|
pref = mMePreference;
|
||||||
} else if (user.isGuest()) {
|
} else if (user.isGuest()) {
|
||||||
pref = new UserPreference(getPrefContext(), null, user.id);
|
// Skip over Guest. We add generic Guest settings after this loop
|
||||||
pref.setTitle(R.string.user_guest);
|
guestId = user.id;
|
||||||
pref.setIcon(getEncircledDefaultIcon());
|
continue;
|
||||||
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);
|
|
||||||
} else {
|
} 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);
|
pref.setKey("id=" + user.id);
|
||||||
userPreferences.add(pref);
|
userPreferences.add(pref);
|
||||||
if (user.isAdmin()) {
|
if (user.isAdmin()) {
|
||||||
pref.setSummary(R.string.user_admin);
|
pref.setSummary(R.string.user_admin);
|
||||||
}
|
}
|
||||||
pref.setTitle(user.name);
|
pref.setTitle(user.name);
|
||||||
pref.setOnPreferenceClickListener(this);
|
pref.setSelectable(false);
|
||||||
pref.setEnabled(canOpenUserDetails);
|
|
||||||
pref.setSelectable(true);
|
|
||||||
}
|
}
|
||||||
if (pref == null) {
|
if (pref == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (user.id != UserHandle.myUserId() && !user.isGuest() && !user.isInitialized()) {
|
if (!isInitialized(user)) {
|
||||||
// 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 (user.isRestricted()) {
|
if (user.isRestricted()) {
|
||||||
pref.setSummary(R.string.user_summary_restricted_not_set_up);
|
pref.setSummary(R.string.user_summary_restricted_not_set_up);
|
||||||
} else {
|
} else {
|
||||||
@@ -966,7 +962,10 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
}
|
}
|
||||||
// Disallow setting up user which results in user switching when the restriction is
|
// Disallow setting up user which results in user switching when the restriction is
|
||||||
// set.
|
// set.
|
||||||
pref.setEnabled(!mUserCaps.mDisallowSwitchUser && canSwitchUserNow());
|
if (!mUserCaps.mDisallowSwitchUser) {
|
||||||
|
pref.setOnPreferenceClickListener(this);
|
||||||
|
pref.setSelectable(mUserManager.canSwitchUsers());
|
||||||
|
}
|
||||||
} else if (user.isRestricted()) {
|
} else if (user.isRestricted()) {
|
||||||
pref.setSummary(R.string.user_summary_restricted_profile);
|
pref.setSummary(R.string.user_summary_restricted_profile);
|
||||||
}
|
}
|
||||||
@@ -987,13 +986,53 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
// Add a temporary entry for the user being created
|
// Add a temporary entry for the user being created
|
||||||
if (mAddingUser) {
|
if (mAddingUser) {
|
||||||
UserPreference pref = new UserPreference(getPrefContext(), null,
|
UserPreference pref = new UserPreference(getPrefContext(), null,
|
||||||
UserPreference.USERID_UNKNOWN);
|
UserPreference.USERID_UNKNOWN, null, null);
|
||||||
pref.setEnabled(false);
|
pref.setEnabled(false);
|
||||||
pref.setTitle(mAddingUserName);
|
pref.setTitle(mAddingUserName);
|
||||||
pref.setIcon(getEncircledDefaultIcon());
|
pref.setIcon(getEncircledDefaultIcon());
|
||||||
userPreferences.add(pref);
|
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
|
// Sort list of users by serialNum
|
||||||
Collections.sort(userPreferences, UserPreference.SERIAL_NUMBER_COMPARATOR);
|
Collections.sort(userPreferences, UserPreference.SERIAL_NUMBER_COMPARATOR);
|
||||||
@@ -1025,7 +1064,6 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
mMultiUserFooterPreferenceController.updateState(multiUserFooterPrefence);
|
mMultiUserFooterPreferenceController.updateState(multiUserFooterPrefence);
|
||||||
mUserListCategory.setVisible(mUserCaps.mUserSwitcherEnabled);
|
mUserListCategory.setVisible(mUserCaps.mUserSwitcherEnabled);
|
||||||
|
|
||||||
updateAddGuest(context, users.stream().anyMatch(UserInfo::isGuest));
|
|
||||||
updateAddUser(context);
|
updateAddUser(context);
|
||||||
|
|
||||||
if (!mUserCaps.mUserSwitcherEnabled) {
|
if (!mUserCaps.mUserSwitcherEnabled) {
|
||||||
@@ -1039,38 +1077,15 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
private void updateAddUser(Context context) {
|
||||||
if ((mUserCaps.mCanAddUser || mUserCaps.mDisallowAddUserSetByAdmin)
|
if ((mUserCaps.mCanAddUser || mUserCaps.mDisallowAddUserSetByAdmin)
|
||||||
&& WizardManagerHelper.isDeviceProvisioned(context)
|
&& WizardManagerHelper.isDeviceProvisioned(context)
|
||||||
&& mUserCaps.mUserSwitcherEnabled) {
|
&& mUserCaps.mUserSwitcherEnabled) {
|
||||||
mAddUser.setVisible(true);
|
mAddUser.setVisible(true);
|
||||||
mAddUser.setSelectable(true);
|
final boolean moreUsers = mUserManager.canAddMoreUsers();
|
||||||
final boolean canAddMoreUsers = mUserManager.canAddMoreUsers();
|
mAddUser.setEnabled(moreUsers && !mAddingUser && mUserManager.canSwitchUsers());
|
||||||
mAddUser.setEnabled(canAddMoreUsers && !mAddingUser && canSwitchUserNow());
|
if (!moreUsers) {
|
||||||
if (!canAddMoreUsers) {
|
mAddUser.setSummary(getString(R.string.user_add_max_count, getMaxRealUsers()));
|
||||||
mAddUser.setSummary(
|
|
||||||
getString(R.string.user_add_max_count, getRealUsersCount()));
|
|
||||||
} else {
|
} else {
|
||||||
mAddUser.setSummary(null);
|
mAddUser.setSummary(null);
|
||||||
}
|
}
|
||||||
@@ -1083,15 +1098,18 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private int getMaxRealUsers() {
|
||||||
* @return number of non-guest non-managed users
|
// guest is not counted against getMaxSupportedUsers() number
|
||||||
*/
|
final int maxUsersAndGuest = UserManager.getMaxSupportedUsers() + 1;
|
||||||
@VisibleForTesting
|
final List<UserInfo> users = mUserManager.getUsers();
|
||||||
int getRealUsersCount() {
|
// managed profiles are counted against getMaxSupportedUsers()
|
||||||
return (int) mUserManager.getUsers()
|
int managedProfiles = 0;
|
||||||
.stream()
|
for (UserInfo user : users) {
|
||||||
.filter(user -> !user.isGuest() && !user.isProfile())
|
if (user.isManagedProfile()) {
|
||||||
.count();
|
managedProfiles++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return maxUsersAndGuest - managedProfiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadIconsAsync(List<Integer> missingIcons) {
|
private void loadIconsAsync(List<Integer> missingIcons) {
|
||||||
@@ -1133,12 +1151,12 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceClick(Preference pref) {
|
public boolean onPreferenceClick(Preference pref) {
|
||||||
if (pref == mMePreference) {
|
if (pref == mMePreference) {
|
||||||
if (isCurrentUserGuest()) {
|
if (mUserCaps.mIsGuest) {
|
||||||
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
|
// 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);
|
onManageUserClicked(UserHandle.myUserId(), false);
|
||||||
} else {
|
} else {
|
||||||
showDialog(DIALOG_USER_PROFILE_EDITOR);
|
showDialog(DIALOG_USER_PROFILE_EDITOR);
|
||||||
@@ -1147,11 +1165,9 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
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 (!isInitialized(user)) {
|
||||||
mHandler.sendMessage(mHandler.obtainMessage(
|
mHandler.sendMessage(mHandler.obtainMessage(
|
||||||
MESSAGE_SETUP_USER, user.id, user.serialNumber));
|
MESSAGE_SETUP_USER, user.id, user.serialNumber));
|
||||||
} else {
|
|
||||||
onManageUserClicked(userId, false);
|
|
||||||
}
|
}
|
||||||
} else if (pref == mAddUser) {
|
} else if (pref == mAddUser) {
|
||||||
// If we allow both types, show a picker, otherwise directly go to
|
// If we allow both types, show a picker, otherwise directly go to
|
||||||
@@ -1161,19 +1177,39 @@ public class UserSettings extends SettingsPreferenceFragment
|
|||||||
} else {
|
} else {
|
||||||
onAddUserClicked(USER_TYPE_USER);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isInitialized(UserInfo user) {
|
||||||
|
return (user.flags & UserInfo.FLAG_INITIALIZED) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
private Drawable encircle(Bitmap icon) {
|
private Drawable encircle(Bitmap icon) {
|
||||||
Drawable circled = CircleFramedDrawable.getInstance(getActivity(), icon);
|
Drawable circled = CircleFramedDrawable.getInstance(getActivity(), icon);
|
||||||
return circled;
|
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
|
@Override
|
||||||
public void onDismiss(DialogInterface dialog) {
|
public void onDismiss(DialogInterface dialog) {
|
||||||
synchronized (mUserLock) {
|
synchronized (mUserLock) {
|
||||||
|
@@ -18,7 +18,6 @@ package com.android.settings.testutils.shadow;
|
|||||||
|
|
||||||
import android.annotation.UserIdInt;
|
import android.annotation.UserIdInt;
|
||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.os.UserManager.EnforcingUser;
|
import android.os.UserManager.EnforcingUser;
|
||||||
@@ -44,18 +43,13 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager
|
|||||||
|
|
||||||
private static boolean sIsSupportsMultipleUsers;
|
private static boolean sIsSupportsMultipleUsers;
|
||||||
|
|
||||||
private final List<String> mBaseRestrictions = new ArrayList<>();
|
private final List<String> mRestrictions = new ArrayList<>();
|
||||||
private final List<String> mUserRestrictions = new ArrayList<>();
|
|
||||||
private final List<String> mGuestRestrictions = new ArrayList<>();
|
|
||||||
private final Map<String, List<EnforcingUser>> mRestrictionSources = new HashMap<>();
|
private final Map<String, List<EnforcingUser>> mRestrictionSources = new HashMap<>();
|
||||||
private final List<UserInfo> mUserProfileInfos = new ArrayList<>();
|
private final List<UserInfo> mUserProfileInfos = new ArrayList<>();
|
||||||
private final Set<Integer> mManagedProfiles = new HashSet<>();
|
private final Set<Integer> mManagedProfiles = new HashSet<>();
|
||||||
private boolean mIsQuietModeEnabled = false;
|
private boolean mIsQuietModeEnabled = false;
|
||||||
private int[] profileIdsForUser = new int[0];
|
private int[] profileIdsForUser = new int[0];
|
||||||
private boolean mUserSwitchEnabled;
|
private boolean mUserSwitchEnabled;
|
||||||
|
|
||||||
private @UserManager.UserSwitchabilityResult int mSwitchabilityStatus =
|
|
||||||
UserManager.SWITCHABILITY_STATUS_OK;
|
|
||||||
private final Map<Integer, Integer> mSameProfileGroupIds = Maps.newHashMap();
|
private final Map<Integer, Integer> mSameProfileGroupIds = Maps.newHashMap();
|
||||||
|
|
||||||
public void addProfile(UserInfo userInfo) {
|
public void addProfile(UserInfo userInfo) {
|
||||||
@@ -88,32 +82,11 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager
|
|||||||
|
|
||||||
@Implementation
|
@Implementation
|
||||||
protected boolean hasBaseUserRestriction(String restrictionKey, UserHandle userHandle) {
|
protected boolean hasBaseUserRestriction(String restrictionKey, UserHandle userHandle) {
|
||||||
return mBaseRestrictions.contains(restrictionKey);
|
return mRestrictions.contains(restrictionKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addBaseUserRestriction(String restriction) {
|
public void addBaseUserRestriction(String restriction) {
|
||||||
mBaseRestrictions.add(restriction);
|
mRestrictions.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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ShadowUserManager getShadow() {
|
public static ShadowUserManager getShadow() {
|
||||||
@@ -193,21 +166,4 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager
|
|||||||
public void setSupportsMultipleUsers(boolean supports) {
|
public void setSupportsMultipleUsers(boolean supports) {
|
||||||
sIsSupportsMultipleUsers = 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -18,8 +18,12 @@ package com.android.settings.users;
|
|||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
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.content.Context;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
import com.android.settingslib.RestrictedPreferenceHelper;
|
import com.android.settingslib.RestrictedPreferenceHelper;
|
||||||
|
|
||||||
@@ -44,12 +48,28 @@ public class UserPreferenceTest {
|
|||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
mContext = RuntimeEnvironment.application;
|
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);
|
ReflectionHelpers.setField(mUserPreference, "mHelper", mRestrictedPreferenceHelper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testShouldHideSecondTarget_shouldHide() {
|
public void testShouldHideSecondTarget_noListener_shouldHide() {
|
||||||
assertThat(mUserPreference.shouldHideSecondTarget()).isTrue();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,14 +16,9 @@
|
|||||||
|
|
||||||
package com.android.settings.users;
|
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 com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.ArgumentMatchers.notNull;
|
import static org.mockito.ArgumentMatchers.notNull;
|
||||||
@@ -31,14 +26,12 @@ import static org.mockito.Mockito.doReturn;
|
|||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.times;
|
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.UserInfo;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
@@ -49,13 +42,14 @@ import android.view.MenuInflater;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.PreferenceCategory;
|
import androidx.preference.PreferenceCategory;
|
||||||
|
import androidx.preference.PreferenceGroup;
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
import androidx.preference.PreferenceScreen;
|
import androidx.preference.PreferenceScreen;
|
||||||
|
|
||||||
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;
|
||||||
import com.android.settingslib.RestrictedLockUtils;
|
|
||||||
import com.android.settingslib.RestrictedPreference;
|
import com.android.settingslib.RestrictedPreference;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
@@ -63,7 +57,6 @@ import org.junit.Before;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.AdditionalMatchers;
|
import org.mockito.AdditionalMatchers;
|
||||||
import org.mockito.ArgumentCaptor;
|
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
@@ -72,7 +65,6 @@ import org.robolectric.android.controller.ActivityController;
|
|||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
import org.robolectric.util.ReflectionHelpers;
|
import org.robolectric.util.ReflectionHelpers;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -81,18 +73,7 @@ import java.util.List;
|
|||||||
public class UserSettingsTest {
|
public class UserSettingsTest {
|
||||||
|
|
||||||
private static final String KEY_USER_GUEST = "user_guest";
|
private static final String KEY_USER_GUEST = "user_guest";
|
||||||
private static final int ACTIVE_USER_ID = 0;
|
private int mProvisioned;
|
||||||
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;
|
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private Drawable mDefaultIconDrawable;
|
private Drawable mDefaultIconDrawable;
|
||||||
@@ -101,10 +82,6 @@ public class UserSettingsTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private UserPreference mMePreference;
|
private UserPreference mMePreference;
|
||||||
@Mock
|
@Mock
|
||||||
private RestrictedPreference mAddUserPreference;
|
|
||||||
@Mock
|
|
||||||
private RestrictedPreference mAddGuestPreference;
|
|
||||||
@Mock
|
|
||||||
private UserManager mUserManager;
|
private UserManager mUserManager;
|
||||||
|
|
||||||
private FragmentActivity mActivity;
|
private FragmentActivity mActivity;
|
||||||
@@ -118,7 +95,6 @@ public class UserSettingsTest {
|
|||||||
mActivity = spy(ActivityController.of(new FragmentActivity()).get());
|
mActivity = spy(ActivityController.of(new FragmentActivity()).get());
|
||||||
mContext = spy(RuntimeEnvironment.application);
|
mContext = spy(RuntimeEnvironment.application);
|
||||||
mUserCapabilities = UserCapabilities.create(mContext);
|
mUserCapabilities = UserCapabilities.create(mContext);
|
||||||
mUserCapabilities.mUserSwitcherEnabled = true;
|
|
||||||
|
|
||||||
mFragment = spy(new UserSettings());
|
mFragment = spy(new UserSettings());
|
||||||
ReflectionHelpers.setField(mFragment, "mAddUserWhenLockedPreferenceController",
|
ReflectionHelpers.setField(mFragment, "mAddUserWhenLockedPreferenceController",
|
||||||
@@ -129,41 +105,100 @@ public class UserSettingsTest {
|
|||||||
ReflectionHelpers.setField(mFragment, "mUserCaps", mUserCapabilities);
|
ReflectionHelpers.setField(mFragment, "mUserCaps", mUserCapabilities);
|
||||||
ReflectionHelpers.setField(mFragment, "mDefaultIconDrawable", mDefaultIconDrawable);
|
ReflectionHelpers.setField(mFragment, "mDefaultIconDrawable", mDefaultIconDrawable);
|
||||||
ReflectionHelpers.setField(mFragment, "mAddingUser", false);
|
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(mActivity).when(mFragment).getActivity();
|
||||||
doReturn(mContext).when(mFragment).getContext();
|
doReturn(mContext).when(mFragment).getContext();
|
||||||
doReturn(mMockPreferenceManager).when(mFragment).getPreferenceManager();
|
doReturn(mMockPreferenceManager).when(mFragment).getPreferenceManager();
|
||||||
doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
|
doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
|
||||||
|
mProvisioned = Settings.Global.getInt(mContext.getContentResolver(),
|
||||||
mProvisionedBackupValue = Settings.Global.getInt(mContext.getContentResolver(),
|
Settings.Global.DEVICE_PROVISIONED, 0);
|
||||||
Settings.Global.DEVICE_PROVISIONED, 0);
|
final SharedPreferences prefs = mock(SharedPreferences .class);
|
||||||
Settings.Global.putInt(mContext.getContentResolver(),
|
when(mMockPreferenceManager.getSharedPreferences()).thenReturn(prefs);
|
||||||
Settings.Global.DEVICE_PROVISIONED, 1); //default state
|
when(mMockPreferenceManager.getContext()).thenReturn(mContext);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
Settings.Global.putInt(mContext.getContentResolver(),
|
Settings.Global.putInt(mContext.getContentResolver(),
|
||||||
Settings.Global.DEVICE_PROVISIONED, mProvisionedBackupValue);
|
Settings.Global.DEVICE_PROVISIONED, mProvisioned);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAssignDefaultPhoto_ContextNull_ReturnFalseAndNotCrash() {
|
public void testAssignDefaultPhoto_ContextNull_ReturnFalseAndNotCrash() {
|
||||||
// Should not crash here
|
// 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
|
@Test
|
||||||
@@ -183,7 +218,7 @@ public class UserSettingsTest {
|
|||||||
ShadowDevicePolicyManager.getShadow().setDeviceOwnerComponentOnAnyUser(
|
ShadowDevicePolicyManager.getShadow().setDeviceOwnerComponentOnAnyUser(
|
||||||
new ComponentName("test", "test"));
|
new ComponentName("test", "test"));
|
||||||
|
|
||||||
doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
|
doReturn(true).when(mUserManager).canSwitchUsers();
|
||||||
mUserCapabilities.mIsAdmin = false;
|
mUserCapabilities.mIsAdmin = false;
|
||||||
|
|
||||||
Menu menu = mock(Menu.class);
|
Menu menu = mock(Menu.class);
|
||||||
@@ -208,7 +243,7 @@ public class UserSettingsTest {
|
|||||||
@Test
|
@Test
|
||||||
public void withoutDisallowRemoveUser_ShouldNotDisableRemoveUser() {
|
public void withoutDisallowRemoveUser_ShouldNotDisableRemoveUser() {
|
||||||
// Arrange
|
// Arrange
|
||||||
doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
|
doReturn(true).when(mUserManager).canSwitchUsers();
|
||||||
mUserCapabilities.mIsAdmin = false;
|
mUserCapabilities.mIsAdmin = false;
|
||||||
|
|
||||||
Menu menu = mock(Menu.class);
|
Menu menu = mock(Menu.class);
|
||||||
@@ -231,457 +266,44 @@ public class UserSettingsTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void updateUserList_canAddUserAndSwitchUser_shouldShowAddUser() {
|
public void updateUserList_canAddUserAndSwitchUser_shouldShowAddUser() {
|
||||||
|
Settings.Global.putInt(mContext.getContentResolver(),
|
||||||
|
Settings.Global.DEVICE_PROVISIONED, 1);
|
||||||
|
final RestrictedPreference addUser = mock(RestrictedPreference.class);
|
||||||
|
|
||||||
mUserCapabilities.mCanAddUser = true;
|
mUserCapabilities.mCanAddUser = true;
|
||||||
doReturn(true).when(mUserManager).canAddMoreUsers();
|
mUserCapabilities.mDisallowAddUser = false;
|
||||||
doReturn(true).when(mAddUserPreference).isEnabled();
|
mUserCapabilities.mUserSwitcherEnabled = true;
|
||||||
doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
|
|
||||||
|
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();
|
mFragment.updateUserList();
|
||||||
|
|
||||||
verify(mAddUserPreference).setVisible(true);
|
verify(addUser).setVisible(true);
|
||||||
verify(mAddUserPreference).setSummary(null);
|
|
||||||
verify(mAddUserPreference).setEnabled(true);
|
|
||||||
verify(mAddUserPreference).setDisabledByAdmin(null);
|
|
||||||
verify(mAddUserPreference).setSelectable(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void updateUserList_canAddGuestAndSwitchUser_shouldShowAddGuest() {
|
public void updateUserList_addUserDisallowedByAdmin_shouldShowAddUserDisabled() {
|
||||||
mUserCapabilities.mCanAddGuest = true;
|
Settings.Global.putInt(mContext.getContentResolver(),
|
||||||
doReturn(true).when(mUserManager).canAddMoreUsers();
|
Settings.Global.DEVICE_PROVISIONED, 1);
|
||||||
doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability();
|
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.mCanAddUser = false;
|
||||||
mUserCapabilities.mDisallowAddUser = true;
|
mUserCapabilities.mDisallowAddUser = true;
|
||||||
mUserCapabilities.mDisallowAddUserSetByAdmin = 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();
|
mFragment.updateUserList();
|
||||||
|
|
||||||
verify(mAddUserPreference).setVisible(true);
|
verify(addUser).setVisible(true);
|
||||||
ArgumentCaptor<RestrictedLockUtils.EnforcedAdmin> captor = ArgumentCaptor.forClass(
|
assertThat(addUser.isEnabled()).isFalse();
|
||||||
RestrictedLockUtils.EnforcedAdmin.class);
|
|
||||||
verify(mAddUserPreference).setDisabledByAdmin(captor.capture());
|
|
||||||
assertThat(captor.getValue()).isEqualTo(enforcedAdmin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user