Merge changes from topics "addSettingsEntrypointToAddASupervisedUser", "simple fallback activity for supervised user creation"
* changes: Create a simple fallback activity for supervised user creation Add settings entrypoint to add a supervised user
This commit is contained in:
committed by
Android (Google) Code Review
commit
1511407370
@@ -2973,6 +2973,12 @@
|
||||
android:value="true" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".users.AddSupervisedUserActivity"
|
||||
android:label="@*android:string/supervised_user_creation_label"
|
||||
android:icon="@drawable/ic_settings_multiuser">
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="Settings$PaymentSettingsActivity"
|
||||
android:label="@string/nfc_payment_settings_title"
|
||||
|
26
res/layout/add_supervised_user.xml
Normal file
26
res/layout/add_supervised_user.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2021 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.
|
||||
-->
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<Button
|
||||
android:id="@+id/createSupervisedUser"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:text="@*android:string/supervised_user_creation_label" />
|
||||
</FrameLayout>
|
@@ -43,6 +43,12 @@
|
||||
android:icon="@drawable/ic_add_40dp"
|
||||
android:order="20"/>
|
||||
|
||||
<com.android.settingslib.RestrictedPreference
|
||||
android:key="supervised_user_add"
|
||||
android:title="@*android:string/supervised_user_creation_label"
|
||||
android:icon="@*android:drawable/ic_add_supervised_user"
|
||||
android:order="25"/>
|
||||
|
||||
<com.android.settingslib.RestrictedSwitchPreference
|
||||
android:key="user_settings_add_users_when_locked"
|
||||
android:title="@string/user_add_on_lockscreen_menu"
|
||||
|
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.users;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.AlertDialog;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.NewUserRequest;
|
||||
import android.os.NewUserResponse;
|
||||
import android.os.UserManager;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Fallback activity for supervised user creation.
|
||||
* Built to test {@link UserManager#createUser(NewUserRequest)} API.
|
||||
*/
|
||||
// TODO(b/209659998): [to-be-removed] fallback activity for supervised user creation.
|
||||
public class AddSupervisedUserActivity extends Activity {
|
||||
|
||||
private UserManager mUserManager;
|
||||
private ActivityManager mActivityManager;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mUserManager = getSystemService(UserManager.class);
|
||||
mActivityManager = getSystemService(ActivityManager.class);
|
||||
setContentView(R.layout.add_supervised_user);
|
||||
findViewById(R.id.createSupervisedUser).setOnClickListener(v -> createUser());
|
||||
}
|
||||
|
||||
private void createUserAsync(final NewUserRequest request,
|
||||
final Consumer<NewUserResponse> onResponse) {
|
||||
Objects.requireNonNull(onResponse);
|
||||
|
||||
final Handler mMainThread = new Handler(Looper.getMainLooper());
|
||||
Executors.newSingleThreadExecutor().execute(() -> {
|
||||
final NewUserResponse response = mUserManager.createUser(request);
|
||||
mMainThread.post(() -> onResponse.accept(response));
|
||||
});
|
||||
}
|
||||
|
||||
private void createUser() {
|
||||
final NewUserRequest request = new NewUserRequest.Builder().build();
|
||||
|
||||
final AlertDialog pleaseWaitDialog = new AlertDialog.Builder(this)
|
||||
.setMessage(getString(R.string.creating_new_user_dialog_message))
|
||||
.setCancelable(false)
|
||||
.create();
|
||||
|
||||
pleaseWaitDialog.show();
|
||||
createUserAsync(request, response -> {
|
||||
pleaseWaitDialog.dismiss();
|
||||
|
||||
if (response.isSuccessful()) {
|
||||
mActivityManager.switchUser(response.getUser());
|
||||
finish();
|
||||
} else {
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.add_user_failed))
|
||||
.setMessage(UserManager.UserOperationResult.class.getName()
|
||||
+ " = " + response.getOperationResult())
|
||||
.setNeutralButton(getString(R.string.okay), null)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@@ -115,6 +115,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
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_SUPERVISED_USER = "supervised_user_add";
|
||||
private static final String KEY_ADD_USER_WHEN_LOCKED = "user_settings_add_users_when_locked";
|
||||
private static final String KEY_MULTIUSER_TOP_INTRO = "multiuser_top_intro";
|
||||
|
||||
@@ -165,10 +166,13 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
@VisibleForTesting
|
||||
RestrictedPreference mAddUser;
|
||||
@VisibleForTesting
|
||||
RestrictedPreference mAddSupervisedUser;
|
||||
@VisibleForTesting
|
||||
SparseArray<Bitmap> mUserIcons = new SparseArray<>();
|
||||
private int mRemovingUserId = -1;
|
||||
private boolean mAddingUser;
|
||||
private boolean mGuestUserAutoCreated;
|
||||
private String mConfigSupervisedUserCreationPackage;
|
||||
private String mAddingUserName;
|
||||
private UserCapabilities mUserCaps;
|
||||
private boolean mShouldUpdateUserList = true;
|
||||
@@ -300,6 +304,10 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
}
|
||||
mAddUser.setOnPreferenceClickListener(this);
|
||||
|
||||
setConfigSupervisedUserCreationPackage();
|
||||
mAddSupervisedUser = findPreference(KEY_ADD_SUPERVISED_USER);
|
||||
mAddSupervisedUser.setOnPreferenceClickListener(this);
|
||||
|
||||
activity.registerReceiverAsUser(
|
||||
mUserChangeReceiver, UserHandle.ALL, USER_REMOVED_INTENT_FILTER, null, mHandler);
|
||||
|
||||
@@ -491,6 +499,21 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
}
|
||||
}
|
||||
|
||||
private void onAddSupervisedUserClicked() {
|
||||
final Intent intent = new Intent()
|
||||
.setAction(UserManager.ACTION_CREATE_SUPERVISED_USER)
|
||||
.setPackage(mConfigSupervisedUserCreationPackage);
|
||||
|
||||
// TODO(b/209659998): [to-be-removed] fallback activity for supervised user creation.
|
||||
if (getActivity().getPackageManager().resolveActivity(intent, 0) == null) {
|
||||
intent
|
||||
.setClass(getContext(), AddSupervisedUserActivity.class)
|
||||
.setPackage(null);
|
||||
}
|
||||
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
private void onRemoveUserClicked(int userId) {
|
||||
synchronized (mUserLock) {
|
||||
if (mRemovingUserId == -1 && !mAddingUser) {
|
||||
@@ -1058,6 +1081,7 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
|
||||
updateAddGuest(context, users.stream().anyMatch(UserInfo::isGuest));
|
||||
updateAddUser(context);
|
||||
updateAddSupervisedUser(context);
|
||||
|
||||
if (!mUserCaps.mUserSwitcherEnabled) {
|
||||
return;
|
||||
@@ -1070,6 +1094,12 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setConfigSupervisedUserCreationPackage() {
|
||||
mConfigSupervisedUserCreationPackage = getPrefContext().getString(
|
||||
com.android.internal.R.string.config_supervisedUserCreationPackage);
|
||||
}
|
||||
|
||||
private boolean isCurrentUserGuest() {
|
||||
return mUserCaps.mIsGuest;
|
||||
}
|
||||
@@ -1100,28 +1130,41 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
}
|
||||
|
||||
private void updateAddUser(Context context) {
|
||||
updateAddUserCommon(context, mAddUser, mUserCaps.mCanAddRestrictedProfile);
|
||||
}
|
||||
|
||||
private void updateAddSupervisedUser(Context context) {
|
||||
if (!TextUtils.isEmpty(mConfigSupervisedUserCreationPackage)) {
|
||||
updateAddUserCommon(context, mAddSupervisedUser, false);
|
||||
} else {
|
||||
mAddSupervisedUser.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAddUserCommon(Context context, RestrictedPreference addUser,
|
||||
boolean canAddRestrictedProfile) {
|
||||
if ((mUserCaps.mCanAddUser || mUserCaps.mDisallowAddUserSetByAdmin)
|
||||
&& WizardManagerHelper.isDeviceProvisioned(context)
|
||||
&& mUserCaps.mUserSwitcherEnabled) {
|
||||
mAddUser.setVisible(true);
|
||||
mAddUser.setSelectable(true);
|
||||
addUser.setVisible(true);
|
||||
addUser.setSelectable(true);
|
||||
final boolean canAddMoreUsers =
|
||||
mUserManager.canAddMoreUsers(UserManager.USER_TYPE_FULL_SECONDARY)
|
||||
|| (mUserCaps.mCanAddRestrictedProfile
|
||||
|| (canAddRestrictedProfile
|
||||
&& mUserManager.canAddMoreUsers(UserManager.USER_TYPE_FULL_RESTRICTED));
|
||||
mAddUser.setEnabled(canAddMoreUsers && !mAddingUser && canSwitchUserNow());
|
||||
addUser.setEnabled(canAddMoreUsers && !mAddingUser && canSwitchUserNow());
|
||||
if (!canAddMoreUsers) {
|
||||
mAddUser.setSummary(
|
||||
addUser.setSummary(
|
||||
getString(R.string.user_add_max_count, getRealUsersCount()));
|
||||
} else {
|
||||
mAddUser.setSummary(null);
|
||||
addUser.setSummary(null);
|
||||
}
|
||||
if (mAddUser.isEnabled()) {
|
||||
mAddUser.setDisabledByAdmin(
|
||||
if (addUser.isEnabled()) {
|
||||
addUser.setDisabledByAdmin(
|
||||
mUserCaps.mDisallowAddUser ? mUserCaps.mEnforcedAdmin : null);
|
||||
}
|
||||
} else {
|
||||
mAddUser.setVisible(false);
|
||||
addUser.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1206,6 +1249,9 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
onAddUserClicked(USER_TYPE_USER);
|
||||
}
|
||||
return true;
|
||||
} else if (pref == mAddSupervisedUser) {
|
||||
onAddSupervisedUserClicked();
|
||||
return true;
|
||||
} else if (pref == mAddGuest) {
|
||||
mAddGuest.setEnabled(false); // prevent multiple tap issue
|
||||
mMetricsFeatureProvider.action(getActivity(), SettingsEnums.ACTION_USER_GUEST_ADD);
|
||||
|
@@ -59,6 +59,7 @@ import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SubSettings;
|
||||
import com.android.settings.testutils.shadow.SettingsShadowResources;
|
||||
import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
|
||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
@@ -85,7 +86,11 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowUserManager.class, ShadowDevicePolicyManager.class})
|
||||
@Config(shadows = {
|
||||
ShadowUserManager.class,
|
||||
ShadowDevicePolicyManager.class,
|
||||
SettingsShadowResources.class,
|
||||
})
|
||||
public class UserSettingsTest {
|
||||
|
||||
private static final String KEY_USER_GUEST = "user_guest";
|
||||
@@ -111,6 +116,8 @@ public class UserSettingsTest {
|
||||
@Mock
|
||||
private RestrictedPreference mAddUserPreference;
|
||||
@Mock
|
||||
private RestrictedPreference mAddSupervisedUserPreference;
|
||||
@Mock
|
||||
private RestrictedPreference mAddGuestPreference;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
@@ -161,6 +168,7 @@ public class UserSettingsTest {
|
||||
|
||||
mFragment.mMePreference = mMePreference;
|
||||
mFragment.mAddUser = mAddUserPreference;
|
||||
mFragment.mAddSupervisedUser = mAddSupervisedUserPreference;
|
||||
mFragment.mAddGuest = mAddGuestPreference;
|
||||
mFragment.mUserListCategory = mock(PreferenceCategory.class);
|
||||
}
|
||||
@@ -169,6 +177,7 @@ public class UserSettingsTest {
|
||||
public void tearDown() {
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.DEVICE_PROVISIONED, mProvisionedBackupValue);
|
||||
SettingsShadowResources.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -694,6 +703,36 @@ public class UserSettingsTest {
|
||||
verify(mUserManager).getUsers();
|
||||
}
|
||||
|
||||
private void setConfigSupervisedUserCreationPackage(String value) {
|
||||
SettingsShadowResources.overrideResource(
|
||||
com.android.internal.R.string.config_supervisedUserCreationPackage,
|
||||
value
|
||||
);
|
||||
mFragment.setConfigSupervisedUserCreationPackage();
|
||||
mUserCapabilities.mCanAddUser = true;
|
||||
mFragment.updateUserList();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addSupervisedUserOption_resourceIsDefined_shouldBeDisplayed() {
|
||||
try {
|
||||
setConfigSupervisedUserCreationPackage("test");
|
||||
verify(mAddSupervisedUserPreference).setVisible(true);
|
||||
} finally {
|
||||
SettingsShadowResources.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addSupervisedUserOption_resourceIsNotDefined_shouldBeHidden() {
|
||||
try {
|
||||
setConfigSupervisedUserCreationPackage("");
|
||||
verify(mAddSupervisedUserPreference).setVisible(false);
|
||||
} finally {
|
||||
SettingsShadowResources.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private void givenUsers(UserInfo... userInfo) {
|
||||
List<UserInfo> users = Arrays.asList(userInfo);
|
||||
doReturn(users).when(mUserManager).getUsers();
|
||||
|
Reference in New Issue
Block a user