Snap for 9354100 from b79c8c6eb4 to udc-release
Change-Id: I5d92b00041be30e7ade64650cfb8e78f4d21b256
This commit is contained in:
@@ -348,7 +348,7 @@
|
||||
android:exported="true"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize">
|
||||
<intent-filter android:priority="1">
|
||||
<action android:name="android.settings.MEMTAG_SETTINGS"/>
|
||||
<action android:name="android.settings.ADVANCED_MEMORY_PROTECTION_SETTINGS"/>
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
|
||||
@@ -105,11 +105,16 @@
|
||||
<item>1800000</item>
|
||||
</string-array>
|
||||
|
||||
<!-- NOTE: if you change this, you must also add the corresponding scale key and lookup table to
|
||||
frameworks/base/core/java/android/content/res/FontScaleLookupTableFactory.java -->
|
||||
<string-array name="entryvalues_font_size" translatable="false">
|
||||
<item>0.85</item>
|
||||
<item>1.0</item>
|
||||
<item>1.15</item>
|
||||
<item>1.30</item>
|
||||
<item>1.50</item>
|
||||
<item>1.80</item>
|
||||
<item>2.0</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Wi-Fi settings -->
|
||||
|
||||
@@ -10492,7 +10492,10 @@
|
||||
<!-- Title for the button to reboot with MTE enabled. [CHAR LIMIT=NONE] -->
|
||||
<string name="reboot_with_mte_title">Reboot with MTE</string>
|
||||
<string name="reboot_with_mte_message">System will reboot and allow to experiment with Memory Tagging Extension (MTE). MTE may negatively impact system performance and stability. Will be reset on next subsequent reboot.</string>
|
||||
<!-- Subtext for button if MTE is not enabled through Advanced memory protection. -->
|
||||
<string name="reboot_with_mte_summary">Try MTE for a single boot for app development</string>
|
||||
<!-- Subtext for button if MTE is already enabled through Advanced memory protection.
|
||||
The string for "Advanced memory protection" needs to match "memtag_toggle" above -->
|
||||
<string name="reboot_with_mte_already_enabled">MTE is enabled through Advanced memory protection</string>
|
||||
<!-- Toast that is shown when the user initiates capturing a heap dump for the system server. [CHAR LIMIT=NONE] -->
|
||||
<string name="capturing_system_heap_dump_message">Capturing system heap dump</string>
|
||||
|
||||
@@ -110,58 +110,57 @@ public class ResetAppsHelper implements DialogInterface.OnClickListener,
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (mResetDialog != dialog) {
|
||||
return;
|
||||
if (mResetDialog == dialog) {
|
||||
resetApps();
|
||||
}
|
||||
AsyncTask.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final List<String> allowList = Arrays.asList(
|
||||
mContext.getResources().getStringArray(
|
||||
R.array.config_skip_reset_apps_package_name));
|
||||
for (UserHandle userHandle : mUm.getEnabledProfiles()) {
|
||||
final int userId = userHandle.getIdentifier();
|
||||
final List<ApplicationInfo> apps = mPm.getInstalledApplicationsAsUser(
|
||||
PackageManager.GET_DISABLED_COMPONENTS, userId);
|
||||
for (int i = 0; i < apps.size(); i++) {
|
||||
ApplicationInfo app = apps.get(i);
|
||||
if (allowList.contains(app.packageName)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/** Resets the app preferences. */
|
||||
public void resetApps() {
|
||||
AsyncTask.execute(() -> {
|
||||
final List<String> allowList = Arrays.asList(
|
||||
mContext.getResources().getStringArray(
|
||||
R.array.config_skip_reset_apps_package_name));
|
||||
for (UserHandle userHandle : mUm.getEnabledProfiles()) {
|
||||
final int userId = userHandle.getIdentifier();
|
||||
final List<ApplicationInfo> apps = mPm.getInstalledApplicationsAsUser(
|
||||
PackageManager.GET_DISABLED_COMPONENTS, userId);
|
||||
for (ApplicationInfo app : apps) {
|
||||
if (allowList.contains(app.packageName)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
mNm.clearData(app.packageName, app.uid, false);
|
||||
} catch (RemoteException ex) {
|
||||
}
|
||||
if (!app.enabled) {
|
||||
try {
|
||||
mNm.clearData(app.packageName, app.uid, false);
|
||||
} catch (android.os.RemoteException ex) {
|
||||
}
|
||||
if (!app.enabled) {
|
||||
try {
|
||||
if (mIPm.getApplicationEnabledSetting(app.packageName, userId)
|
||||
== PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
|
||||
mIPm.setApplicationEnabledSetting(app.packageName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
|
||||
PackageManager.DONT_KILL_APP,
|
||||
userId,
|
||||
mContext.getPackageName());
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error during reset disabled apps.", e);
|
||||
if (mIPm.getApplicationEnabledSetting(app.packageName, userId)
|
||||
== PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
|
||||
mIPm.setApplicationEnabledSetting(app.packageName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
|
||||
PackageManager.DONT_KILL_APP,
|
||||
userId,
|
||||
mContext.getPackageName());
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error during reset disabled apps.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
mIPm.resetApplicationPreferences(UserHandle.myUserId());
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
mAom.resetAllModes();
|
||||
BatteryOptimizeUtils.resetAppOptimizationMode(mContext, mIPm, mAom);
|
||||
final int[] restrictedUids = mNpm.getUidsWithPolicy(
|
||||
POLICY_REJECT_METERED_BACKGROUND);
|
||||
final int currentUserId = ActivityManager.getCurrentUser();
|
||||
for (int uid : restrictedUids) {
|
||||
// Only reset for current user
|
||||
if (UserHandle.getUserId(uid) == currentUserId) {
|
||||
mNpm.setUidPolicy(uid, POLICY_NONE);
|
||||
}
|
||||
}
|
||||
try {
|
||||
mIPm.resetApplicationPreferences(UserHandle.myUserId());
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
mAom.resetAllModes();
|
||||
BatteryOptimizeUtils.resetAppOptimizationMode(mContext, mIPm, mAom);
|
||||
final int[] restrictedUids = mNpm.getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND);
|
||||
final int currentUserId = ActivityManager.getCurrentUser();
|
||||
for (int uid : restrictedUids) {
|
||||
// Only reset for current user
|
||||
if (UserHandle.getUserId(uid) == currentUserId) {
|
||||
mNpm.setUidPolicy(uid, POLICY_NONE);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -84,7 +84,7 @@ public class PictureInPictureDetails extends AppInfoWithHeader
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return SettingsEnums.SETTINGS_MANAGE_PICTURE_IN_PICTURE;
|
||||
return SettingsEnums.SETTINGS_MANAGE_PICTURE_IN_PICTURE_DETAIL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.settings.dashboard.profileselector;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
@@ -41,7 +42,6 @@ import com.android.settings.deviceinfo.storage.StorageEntry;
|
||||
import com.android.settings.deviceinfo.storage.StorageSelectionPreferenceController;
|
||||
import com.android.settings.deviceinfo.storage.StorageUsageProgressBarPreferenceController;
|
||||
import com.android.settings.deviceinfo.storage.StorageUtils;
|
||||
import com.android.settingslib.core.instrumentation.Instrumentable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -323,7 +323,7 @@ public class ProfileSelectStorageFragment extends ProfileSelectFragment {
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return Instrumentable.METRICS_CATEGORY_UNKNOWN;
|
||||
return SettingsEnums.SETTINGS_STORAGE_PROFILE_SELECTOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -64,8 +64,8 @@ public class NonCurrentUserController extends AbstractPreferenceController imple
|
||||
* Adds the appropriate controllers to a controller list for handling all full non current
|
||||
* users on a device.
|
||||
*
|
||||
* @param context Context for initializing the preference controllers.
|
||||
* @param userManager UserManagerWrapper for figuring out which controllers to add.
|
||||
* @param context Context for initializing the preference controllers.
|
||||
* @param userManager UserManagerWrapper for figuring out which controllers to add.
|
||||
*/
|
||||
public static List<NonCurrentUserController> getNonCurrentUserControllers(
|
||||
Context context, UserManager userManager) {
|
||||
@@ -73,7 +73,7 @@ public class NonCurrentUserController extends AbstractPreferenceController imple
|
||||
List<NonCurrentUserController> controllers = new ArrayList<>();
|
||||
List<UserInfo> infos = userManager.getUsers();
|
||||
for (UserInfo info : infos) {
|
||||
if (info.id == currentUserId || info.isProfile()) {
|
||||
if (info.id == currentUserId || !info.isFull()) {
|
||||
continue;
|
||||
}
|
||||
int[] profiles = userManager.getProfileIds(info.id, false /* enabledOnly */);
|
||||
@@ -85,8 +85,8 @@ public class NonCurrentUserController extends AbstractPreferenceController imple
|
||||
/**
|
||||
* Constructor for a given non-current user.
|
||||
*
|
||||
* @param context Context to initialize the underlying {@link AbstractPreferenceController}.
|
||||
* @param info {@link UserInfo} for the non-current user which these controllers cover.
|
||||
* @param context Context to initialize the underlying {@link AbstractPreferenceController}.
|
||||
* @param info {@link UserInfo} for the non-current user which these controllers cover.
|
||||
* @param profiles list of IDs or user and its profiles
|
||||
*/
|
||||
@VisibleForTesting
|
||||
|
||||
@@ -33,10 +33,10 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.android.internal.os.BatteryStatsHistoryIterator;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.widget.UsageView;
|
||||
import com.android.settingslib.R;
|
||||
import com.android.settingslib.fuelgauge.Estimate;
|
||||
import com.android.settingslib.fuelgauge.EstimateKt;
|
||||
import com.android.settingslib.utils.PowerUtil;
|
||||
|
||||
@@ -602,15 +602,6 @@ public class BatteryUtils {
|
||||
/*receiver=*/ null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
}
|
||||
|
||||
/** Gets the battery level from the intent. */
|
||||
public static int getBatteryLevel(Intent intent) {
|
||||
final int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
|
||||
final int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
|
||||
return scale == 0
|
||||
? -1 /*invalid battery level*/
|
||||
: Math.round((level / (float) scale) * 100f);
|
||||
}
|
||||
|
||||
/** Gets the current dock defender mode */
|
||||
public static int getCurrentDockDefenderMode(Context context, BatteryInfo batteryInfo) {
|
||||
if (batteryInfo.pluggedStatus == BatteryManager.BATTERY_PLUGGED_DOCK) {
|
||||
|
||||
@@ -36,6 +36,7 @@ import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settings.fuelgauge.BatteryUtils;
|
||||
import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDatabase;
|
||||
import com.android.settingslib.fuelgauge.BatteryStatus;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Duration;
|
||||
@@ -149,7 +150,7 @@ public final class DatabaseUtils {
|
||||
clearMemory();
|
||||
return null;
|
||||
}
|
||||
final int batteryLevel = BatteryUtils.getBatteryLevel(intent);
|
||||
final int batteryLevel = BatteryStatus.getBatteryLevel(intent);
|
||||
final int batteryStatus = intent.getIntExtra(
|
||||
BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_UNKNOWN);
|
||||
final int batteryHealth = intent.getIntExtra(
|
||||
|
||||
@@ -58,14 +58,15 @@ object AllAppListPageProvider : SettingsPageProvider {
|
||||
|
||||
@Composable
|
||||
private fun AllAppListPage() {
|
||||
val resetAppDialogPresenter = rememberResetAppDialogPresenter()
|
||||
AppListPage(
|
||||
title = stringResource(R.string.all_apps),
|
||||
listModel = remember { AllAppListModel() },
|
||||
showInstantApps = true,
|
||||
) { itemModel ->
|
||||
moreOptions = { ResetAppPreferences(resetAppDialogPresenter::open) }
|
||||
) {
|
||||
AppListItem(
|
||||
itemModel = itemModel,
|
||||
onClick = AppInfoSettingsProvider.navigator(app = itemModel.record.app),
|
||||
onClick = AppInfoSettingsProvider.navigator(app = record.app),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
60
src/com/android/settings/spa/app/ResetAppPreferences.kt
Normal file
60
src/com/android/settings/spa/app/ResetAppPreferences.kt
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.spa.app
|
||||
|
||||
import android.os.UserHandle
|
||||
import android.os.UserManager
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.android.settings.R
|
||||
import com.android.settings.applications.manageapplications.ResetAppsHelper
|
||||
import com.android.settingslib.spa.widget.dialog.AlertDialogButton
|
||||
import com.android.settingslib.spa.widget.dialog.AlertDialogPresenter
|
||||
import com.android.settingslib.spa.widget.dialog.rememberAlertDialogPresenter
|
||||
import com.android.settingslib.spa.widget.scaffold.MoreOptionsScope
|
||||
import com.android.settingslib.spaprivileged.model.enterprise.Restrictions
|
||||
import com.android.settingslib.spaprivileged.template.scaffold.RestrictedMenuItem
|
||||
|
||||
@Composable
|
||||
fun MoreOptionsScope.ResetAppPreferences(onClick: () -> Unit) {
|
||||
RestrictedMenuItem(
|
||||
text = stringResource(R.string.reset_app_preferences),
|
||||
restrictions = remember {
|
||||
Restrictions(
|
||||
userId = UserHandle.myUserId(),
|
||||
keys = listOf(UserManager.DISALLOW_APPS_CONTROL),
|
||||
)
|
||||
},
|
||||
onClick = onClick,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberResetAppDialogPresenter(): AlertDialogPresenter {
|
||||
val context = LocalContext.current
|
||||
return rememberAlertDialogPresenter(
|
||||
confirmButton = AlertDialogButton(stringResource(R.string.reset_app_preferences_button)) {
|
||||
ResetAppsHelper(context).resetApps()
|
||||
},
|
||||
dismissButton = AlertDialogButton(stringResource(R.string.cancel)),
|
||||
title = stringResource(R.string.reset_app_preferences_title),
|
||||
text = { Text(stringResource(R.string.reset_app_preferences_desc)) },
|
||||
)
|
||||
}
|
||||
@@ -37,9 +37,7 @@ object UsageStatsPageProvider : SettingsPageProvider {
|
||||
title = stringResource(R.string.testing_usage_stats),
|
||||
listModel = rememberContext(::UsageStatsListModel),
|
||||
primaryUserOnly = true,
|
||||
) { itemModel ->
|
||||
AppListItem(itemModel) {}
|
||||
}
|
||||
) { AppListItem {} }
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -46,9 +46,7 @@ object AppListNotificationsPageProvider : SettingsPageProvider {
|
||||
AppListPage(
|
||||
title = stringResource(R.string.app_notifications_title),
|
||||
listModel = rememberContext(::AppNotificationsListModel),
|
||||
) {
|
||||
AppNotificationsItem(it)
|
||||
}
|
||||
) { AppNotificationsItem() }
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -62,24 +60,21 @@ object AppListNotificationsPageProvider : SettingsPageProvider {
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AppNotificationsItem(
|
||||
itemModel: AppListItemModel<AppNotificationsRecord>,
|
||||
) {
|
||||
private fun AppListItemModel<AppNotificationsRecord>.AppNotificationsItem() {
|
||||
val appNotificationsRepository = rememberContext(::AppNotificationRepository)
|
||||
val context = LocalContext.current
|
||||
AppListSwitchItem(
|
||||
itemModel = itemModel,
|
||||
onClick = {
|
||||
navigateToAppNotificationSettings(
|
||||
context = context,
|
||||
app = itemModel.record.app,
|
||||
app = record.app,
|
||||
)
|
||||
},
|
||||
checked = itemModel.record.controller.isEnabled.observeAsState(),
|
||||
checked = record.controller.isEnabled.observeAsState(),
|
||||
changeable = produceState(initialValue = false) {
|
||||
value = appNotificationsRepository.isChangeable(itemModel.record.app)
|
||||
value = appNotificationsRepository.isChangeable(record.app)
|
||||
},
|
||||
onCheckedChange = itemModel.record.controller::setEnabled,
|
||||
onCheckedChange = record.controller::setEnabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -52,9 +52,7 @@ object AppLanguagesPageProvider : SettingsPageProvider {
|
||||
SettingsBody(stringResource(R.string.desc_app_locale_selection_supported))
|
||||
}
|
||||
},
|
||||
) {
|
||||
AppLanguageItem(it)
|
||||
}
|
||||
) { AppLanguageItem() }
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -68,16 +66,13 @@ object AppLanguagesPageProvider : SettingsPageProvider {
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AppLanguageItem(itemModel: AppListItemModel<AppLanguagesRecord>) {
|
||||
private fun AppListItemModel<AppLanguagesRecord>.AppLanguageItem() {
|
||||
val context = LocalContext.current
|
||||
AppListItem(
|
||||
itemModel = itemModel,
|
||||
onClick = {
|
||||
val intent = Intent(context, AppLocalePickerActivity::class.java).apply {
|
||||
setData(Uri.parse("package:${itemModel.record.app.packageName}"))
|
||||
putExtra("uid", itemModel.record.app.uid)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
AppListItem {
|
||||
val intent = Intent(context, AppLocalePickerActivity::class.java).apply {
|
||||
data = Uri.parse("package:${record.app.packageName}")
|
||||
putExtra("uid", record.app.uid)
|
||||
}
|
||||
)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,8 +317,12 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
|
||||
mRemoveUserPref.setTitle(R.string.user_remove_user);
|
||||
removePreference(KEY_APP_COPYING);
|
||||
}
|
||||
|
||||
// Remove preference KEY_REMOVE_USER if DISALLOW_REMOVE_USER restriction is set
|
||||
// on the current user or the user selected in user details settings is a main user.
|
||||
if (RestrictedLockUtilsInternal.hasBaseUserRestriction(context,
|
||||
UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId())) {
|
||||
UserManager.DISALLOW_REMOVE_USER, UserHandle.myUserId())
|
||||
|| mUserInfo.isMain()) {
|
||||
removePreference(KEY_REMOVE_USER);
|
||||
}
|
||||
|
||||
@@ -331,7 +335,7 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
|
||||
|
||||
@VisibleForTesting
|
||||
boolean canDeleteUser() {
|
||||
if (!mUserManager.isAdminUser()) {
|
||||
if (!mUserManager.isAdminUser() || mUserInfo.isMain()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -97,6 +97,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -240,9 +241,6 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
case MESSAGE_UPDATE_LIST:
|
||||
updateUserList();
|
||||
break;
|
||||
case MESSAGE_USER_CREATED:
|
||||
onUserCreated(msg.arg1);
|
||||
break;
|
||||
case MESSAGE_REMOVE_GUEST_ON_EXIT_CONTROLLER_GUEST_REMOVED:
|
||||
updateUserList();
|
||||
if (mGuestUserAutoCreated) {
|
||||
@@ -624,14 +622,13 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
}
|
||||
}
|
||||
|
||||
private void onUserCreated(int userId) {
|
||||
private void onUserCreated(UserInfo userInfo) {
|
||||
hideUserCreatingDialog();
|
||||
// prevent crash when config changes during user creation
|
||||
if (getContext() == null) {
|
||||
return;
|
||||
}
|
||||
mAddingUser = false;
|
||||
UserInfo userInfo = mUserManager.getUserInfo(userId);
|
||||
openUserDetails(userInfo, true);
|
||||
}
|
||||
|
||||
@@ -1011,69 +1008,50 @@ public class UserSettings extends SettingsPreferenceFragment
|
||||
|
||||
mUserCreatingDialog = new UserCreatingDialog(getActivity());
|
||||
mUserCreatingDialog.show();
|
||||
ThreadUtils.postOnBackgroundThread(new AddUserNowImpl(userType, mAddingUserName));
|
||||
createUser(userType, mAddingUserName);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
class AddUserNowImpl implements Runnable{
|
||||
int mUserType;
|
||||
String mImplAddUserName;
|
||||
|
||||
AddUserNowImpl(final int userType, final String addUserName) {
|
||||
mUserType = userType;
|
||||
mImplAddUserName = addUserName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
runAddUser();
|
||||
Trace.endAsyncSection("UserSettings.addUserNow", 0);
|
||||
}
|
||||
|
||||
private void runAddUser() {
|
||||
void createUser(final int userType, String userName) {
|
||||
Future<?> unusedCreateUserFuture = ThreadUtils.postOnBackgroundThread(() -> {
|
||||
UserInfo user;
|
||||
String username;
|
||||
|
||||
synchronized (mUserLock) {
|
||||
username = mImplAddUserName;
|
||||
}
|
||||
|
||||
// Could take a few seconds
|
||||
if (mUserType == USER_TYPE_USER) {
|
||||
user = mUserManager.createUser(username, 0);
|
||||
if (userType == USER_TYPE_USER) {
|
||||
user = mUserManager.createUser(
|
||||
userName,
|
||||
mUserManager.USER_TYPE_FULL_SECONDARY,
|
||||
0);
|
||||
} else {
|
||||
user = mUserManager.createRestrictedProfile(username);
|
||||
user = mUserManager.createRestrictedProfile(userName);
|
||||
}
|
||||
|
||||
synchronized (mUserLock) {
|
||||
ThreadUtils.postOnMainThread(() -> {
|
||||
if (user == null) {
|
||||
mAddingUser = false;
|
||||
mPendingUserIcon = null;
|
||||
mPendingUserName = null;
|
||||
ThreadUtils.postOnMainThread(() -> onUserCreationFailed());
|
||||
onUserCreationFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
Drawable newUserIcon = mPendingUserIcon;
|
||||
if (newUserIcon == null) {
|
||||
newUserIcon = UserIcons.getDefaultUserIcon(getResources(), user.id, false);
|
||||
}
|
||||
mUserManager.setUserIcon(
|
||||
user.id, UserIcons.convertToBitmapAtUserIconSize(
|
||||
getResources(), newUserIcon));
|
||||
|
||||
if (mUserType == USER_TYPE_USER) {
|
||||
mHandler.sendEmptyMessage(MESSAGE_UPDATE_LIST);
|
||||
}
|
||||
|
||||
mHandler.sendMessage(mHandler.obtainMessage(
|
||||
MESSAGE_USER_CREATED, user.id, user.serialNumber));
|
||||
Future<?> unusedSettingIconFuture = ThreadUtils.postOnBackgroundThread(() -> {
|
||||
Drawable newUserIcon = mPendingUserIcon;
|
||||
if (newUserIcon == null) {
|
||||
newUserIcon = UserIcons.getDefaultUserIcon(getResources(), user.id, false);
|
||||
}
|
||||
mUserManager.setUserIcon(
|
||||
user.id, UserIcons.convertToBitmapAtUserIconSize(
|
||||
getResources(), newUserIcon));
|
||||
});
|
||||
|
||||
mPendingUserIcon = null;
|
||||
mPendingUserName = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onUserCreated(user);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Erase the current user (guest) and switch to another user.
|
||||
|
||||
@@ -35,7 +35,6 @@ import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import com.android.settings.Settings;
|
||||
import com.android.settings.testutils.AdbUtils;
|
||||
import com.android.settings.testutils.UiUtils;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -87,8 +86,7 @@ public class UserSettingsComponentTest {
|
||||
((FragmentActivity) activity).getSupportFragmentManager().getFragments().get(0);
|
||||
UserSettings us = (UserSettings) f;
|
||||
Log.d(TAG, "Start to add user :" + randomUserName);
|
||||
ThreadUtils.postOnBackgroundThread(
|
||||
us.new AddUserNowImpl(USER_TYPE_RESTRICTED_PROFILE, randomUserName));
|
||||
us.createUser(USER_TYPE_RESTRICTED_PROFILE, randomUserName);
|
||||
});
|
||||
|
||||
assertThat(
|
||||
|
||||
@@ -80,7 +80,7 @@ public class NonCurrentUserControllerTest {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mPrimaryUser = new UserInfo();
|
||||
mPrimaryUser.flags = UserInfo.FLAG_PRIMARY;
|
||||
mPrimaryUser.flags = UserInfo.FLAG_PRIMARY | UserInfo.FLAG_FULL;
|
||||
mController = new NonCurrentUserController(mContext, mPrimaryUser);
|
||||
ShadowActivityManager.setService(mActivityService);
|
||||
|
||||
@@ -267,6 +267,8 @@ public class NonCurrentUserControllerTest {
|
||||
secondaryUser.id = 10;
|
||||
final UserInfo secondaryUser1 = spy(new UserInfo());
|
||||
secondaryUser1.id = 11;
|
||||
secondaryUser.flags = UserInfo.FLAG_FULL;
|
||||
secondaryUser1.flags = UserInfo.FLAG_FULL;
|
||||
userInfo.add(mPrimaryUser);
|
||||
userInfo.add(secondaryUser);
|
||||
userInfo.add(secondaryUser1);
|
||||
|
||||
@@ -132,6 +132,7 @@ public final class BatteryUsageBroadcastReceiverTest {
|
||||
private static Intent getBatteryIntent(int level, int status) {
|
||||
final Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
|
||||
intent.putExtra(BatteryManager.EXTRA_LEVEL, level);
|
||||
intent.putExtra(BatteryManager.EXTRA_SCALE, 100);
|
||||
intent.putExtra(BatteryManager.EXTRA_STATUS, status);
|
||||
return intent;
|
||||
}
|
||||
|
||||
@@ -387,6 +387,16 @@ public class UserDetailsSettingsTest {
|
||||
verify(mFragment).removePreference(KEY_REMOVE_USER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initialize_onMainUser_shouldNotShowRemovePreference() {
|
||||
setupSelectedMainUser();
|
||||
mUserManager.setIsAdminUser(true);
|
||||
|
||||
mFragment.initialize(mActivity, mArguments);
|
||||
|
||||
verify(mFragment).removePreference(KEY_REMOVE_USER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initialize_disallowRemoveUserRestriction_shouldNotShowRemovePreference() {
|
||||
setupSelectedUser();
|
||||
@@ -571,10 +581,22 @@ public class UserDetailsSettingsTest {
|
||||
assertThat(result).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canDeleteUser_onMainUser_shouldReturnFalse() {
|
||||
setupSelectedMainUser();
|
||||
mUserManager.setIsAdminUser(true);
|
||||
mFragment.mUserInfo = mUserInfo;
|
||||
|
||||
boolean result = mFragment.canDeleteUser();
|
||||
|
||||
assertThat(result).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canDeleteUser_adminSelectsUser_noRestrictions_shouldReturnTrue() {
|
||||
setupSelectedUser();
|
||||
mUserManager.setIsAdminUser(true);
|
||||
mFragment.mUserInfo = mUserInfo;
|
||||
|
||||
boolean result = mFragment.canDeleteUser();
|
||||
|
||||
@@ -585,6 +607,7 @@ public class UserDetailsSettingsTest {
|
||||
public void canDeleteUser_adminSelectsUser_hasRemoveRestriction_shouldReturnFalse() {
|
||||
setupSelectedUser();
|
||||
mUserManager.setIsAdminUser(true);
|
||||
mFragment.mUserInfo = mUserInfo;
|
||||
ComponentName componentName = new ComponentName("test", "test");
|
||||
ShadowDevicePolicyManager.getShadow().setDeviceOwnerComponentOnAnyUser(componentName);
|
||||
ShadowDevicePolicyManager.getShadow().setDeviceOwnerUserId(UserHandle.myUserId());
|
||||
@@ -611,6 +634,15 @@ public class UserDetailsSettingsTest {
|
||||
mUserManager.addProfile(mUserInfo);
|
||||
}
|
||||
|
||||
private void setupSelectedMainUser() {
|
||||
mArguments.putInt("user_id", 11);
|
||||
mUserInfo = new UserInfo(11, "Jerry", null,
|
||||
UserInfo.FLAG_FULL | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_MAIN,
|
||||
UserManager.USER_TYPE_FULL_SECONDARY);
|
||||
|
||||
mUserManager.addProfile(mUserInfo);
|
||||
}
|
||||
|
||||
private void setupSelectedGuest() {
|
||||
mArguments.putInt("user_id", 23);
|
||||
mUserInfo = new UserInfo(23, "Guest", null,
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.spa.app
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.settings.R
|
||||
import com.android.settingslib.spa.widget.scaffold.MoreOptionsScope
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Spy
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ResetAppPreferencesTest {
|
||||
@get:Rule
|
||||
val composeTestRule = createComposeRule()
|
||||
|
||||
@Spy
|
||||
private val context: Context = ApplicationProvider.getApplicationContext()
|
||||
|
||||
@Test
|
||||
fun resetAppPreferences_titleIsDisplayed() {
|
||||
setResetAppPreferences()
|
||||
|
||||
composeTestRule.onNodeWithText(context.getString(R.string.reset_app_preferences))
|
||||
.assertIsDisplayed()
|
||||
}
|
||||
|
||||
private fun setResetAppPreferences() {
|
||||
val fakeMoreOptionsScope = object : MoreOptionsScope {
|
||||
override fun dismiss() {}
|
||||
}
|
||||
composeTestRule.setContent {
|
||||
fakeMoreOptionsScope.ResetAppPreferences {}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun resetAppDialogPresenter_confirmButtonDisplayed() {
|
||||
setAndOpenDialog()
|
||||
|
||||
composeTestRule.onNodeWithText(context.getString(R.string.reset_app_preferences_button))
|
||||
.assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun resetAppDialogPresenter_titleDisplayed() {
|
||||
setAndOpenDialog()
|
||||
|
||||
composeTestRule.onNodeWithText(context.getString(R.string.reset_app_preferences_title))
|
||||
.assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun resetAppDialogPresenter_textDisplayed() {
|
||||
setAndOpenDialog()
|
||||
|
||||
composeTestRule.onNodeWithText(context.getString(R.string.reset_app_preferences_desc))
|
||||
.assertIsDisplayed()
|
||||
}
|
||||
|
||||
private fun setAndOpenDialog() {
|
||||
composeTestRule.setContent {
|
||||
val dialogPresenter = rememberResetAppDialogPresenter()
|
||||
LaunchedEffect(Unit) {
|
||||
dialogPresenter.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,20 +179,8 @@ public class FingerprintStatusUtilsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSettingsClassName_whenNotEnrolled_fingerprintOnly_returnsFingerprintEnrollInduction() {
|
||||
public void getSettingsClassName_whenNotEnrolled_returnsFingerprintSettings() {
|
||||
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
|
||||
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
|
||||
when(mFaceManager.isHardwareDetected()).thenReturn(false);
|
||||
|
||||
assertThat(mFingerprintStatusUtils.getSettingsClassName())
|
||||
.isEqualTo(FingerprintEnrollIntroductionInternal.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSettingsClassName_whenNotEnrolled_fingerprintNotOnly_returnsFingerprintSettings() {
|
||||
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
|
||||
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
|
||||
when(mFaceManager.isHardwareDetected()).thenReturn(true);
|
||||
|
||||
assertThat(mFingerprintStatusUtils.getSettingsClassName())
|
||||
.isEqualTo(FingerprintSettings.class.getName());
|
||||
|
||||
Reference in New Issue
Block a user