Snap for 11330025 from b34e67228f to 24Q2-release

Change-Id: Ie93e56816277d813cf1c3a6c7dabf675c1d6146e
This commit is contained in:
Android Build Coastguard Worker
2024-01-19 00:21:03 +00:00
14 changed files with 347 additions and 105 deletions

View File

@@ -5036,6 +5036,12 @@
android:authorities="${applicationId}.androidx-startup"
tools:node="remove" />
<activity
android:name="com.android.settings.network.WepNetworkDialogActivity"
android:exported="false"
android:theme="@style/Theme.SpaLib.Dialog">
</activity>
<!-- This is the longest AndroidManifest.xml ever. -->
</application>
</manifest>

View File

@@ -3323,6 +3323,8 @@
<string name="menu_cancel">Cancel</string>
<!-- APN error dialog title -->
<string name="error_title"></string>
<!-- APN error dialog messages when the new apn is a duplicate: -->
<string name="error_duplicate_apn_entry">Duplicate apn entry.</string>
<!-- APN error dialog messages: -->
<string name="error_name_empty">The Name field can\u2019t be empty.</string>
<!-- APN error dialog messages: -->

View File

@@ -149,6 +149,7 @@ public class HearingDevicePairingFragment extends RestrictedDashboardFragment im
for (BluetoothGatt gatt: mConnectingGattList) {
gatt.disconnect();
}
mConnectingGattList.clear();
mLocalManager.setForegroundActivity(null);
mLocalManager.getEventManager().unregisterCallback(this);
}

View File

@@ -89,6 +89,7 @@ import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.LayoutPreference;
import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils;
import com.android.settingslib.wifi.WifiSavedConfigUtils;
import com.android.wifi.flags.Flags;
import com.android.wifitrackerlib.WifiEntry;
import com.android.wifitrackerlib.WifiEntry.ConnectCallback;
import com.android.wifitrackerlib.WifiPickerTracker;
@@ -1257,8 +1258,19 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment
// If it's an unsaved secure WifiEntry, it will callback
// ConnectCallback#onConnectResult with ConnectCallback#CONNECT_STATUS_FAILURE_NO_CONFIG
wifiEntry.connect(new WifiEntryConnectCallback(wifiEntry, editIfNoConfig,
fullScreenEdit));
WifiEntryConnectCallback callback =
new WifiEntryConnectCallback(wifiEntry, editIfNoConfig, fullScreenEdit);
if (Flags.wepUsage() && wifiEntry.getSecurityTypes().contains(WifiEntry.SECURITY_WEP)) {
WepNetworkDialogActivity.checkWepAllowed(
getContext(), getViewLifecycleOwner(), wifiEntry.getSsid(), () -> {
wifiEntry.connect(callback);
return null;
});
return;
}
wifiEntry.connect(callback);
}
private class WifiConnectActionListener implements WifiManager.ActionListener {

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2024 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.network
import android.app.settings.SettingsEnums
import android.content.Context
import android.content.Intent
import android.net.wifi.WifiManager
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextAlign
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import com.android.settings.R
import com.android.settings.core.SubSettingLauncher
import com.android.settings.wifi.ConfigureWifiSettings
import com.android.settingslib.spa.SpaBaseDialogActivity
import com.android.settingslib.spa.widget.dialog.AlertDialogButton
import com.android.settingslib.spa.widget.dialog.SettingsAlertDialogWithIcon
import kotlin.coroutines.resume
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asExecutor
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
class WepNetworkDialogActivity : SpaBaseDialogActivity() {
@Composable
override fun Content() {
val context = LocalContext.current
val wifiManager = context.getSystemService(WifiManager::class.java)
SettingsAlertDialogWithIcon(
onDismissRequest = { finish() },
confirmButton = AlertDialogButton(
getString(R.string.wifi_settings_ssid_block_button_close)
) { finish() },
dismissButton = AlertDialogButton(
getString(R.string.wifi_settings_wep_networks_button_allow)
) {
SubSettingLauncher(context)
.setTitleText(context.getText(R.string.network_and_internet_preferences_title))
.setSourceMetricsCategory(SettingsEnums.CONFIGURE_WIFI)
.setDestination(ConfigureWifiSettings::class.java.getName())
.launch()
finish()
},
title = String.format(
getString(R.string.wifi_settings_wep_networks_blocked_title),
intent.getStringExtra(SSID) ?: SSID
),
text = {
Text(
if (wifiManager?.isWepSupported == false)
getString(R.string.wifi_settings_wep_networks_summary_toggle_off)
else getString(R.string.wifi_settings_wep_networks_summary_blocked_by_carrier),
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center
)
})
}
companion object {
@JvmStatic
fun checkWepAllowed(
context: Context,
lifecycleOwner: LifecycleOwner,
ssid: String,
onAllowed: () -> Unit,
) {
lifecycleOwner.lifecycleScope.launch {
val wifiManager = context.getSystemService(WifiManager::class.java) ?: return@launch
if (wifiManager.queryWepAllowed()) {
onAllowed()
} else {
val intent = Intent(context, WepNetworkDialogActivity::class.java).apply {
putExtra(SSID, ssid)
}
context.startActivity(intent)
}
}
}
private suspend fun WifiManager.queryWepAllowed(): Boolean =
withContext(Dispatchers.Default) {
suspendCancellableCoroutine { continuation ->
queryWepAllowed(Dispatchers.Default.asExecutor()) {
continuation.resume(it)
}
}
}
const val SSID = "ssid"
}
}

View File

@@ -19,16 +19,19 @@ package com.android.settings.network.apn
import android.net.Uri
import android.os.Bundle
import androidx.compose.foundation.layout.Column
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Done
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringArrayResource
import androidx.compose.ui.res.stringResource
@@ -39,14 +42,14 @@ import com.android.settings.network.apn.ApnNetworkTypes.getNetworkTypeDisplayNam
import com.android.settings.network.apn.ApnNetworkTypes.getNetworkTypeSelectedOptionsState
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.LocalNavController
import com.android.settingslib.spa.framework.theme.SettingsDimension
import com.android.settingslib.spa.widget.editor.SettingsExposedDropdownMenuBox
import com.android.settingslib.spa.widget.editor.SettingsExposedDropdownMenuCheckBox
import com.android.settingslib.spa.widget.editor.SettingsOutlinedTextField
import com.android.settingslib.spa.widget.editor.SettingsTextFieldPassword
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spa.widget.preference.SwitchPreference
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
import com.android.settingslib.spa.widget.scaffold.MoreOptionsAction
import com.android.settingslib.spa.widget.scaffold.RegularScaffold
import java.util.Base64
@@ -98,25 +101,59 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur
getNetworkTypeSelectedOptionsState(apnData.networkType)
}
val navController = LocalNavController.current
var valid: String?
RegularScaffold(
title = if (apnDataInit.newApn) stringResource(id = R.string.apn_add) else stringResource(id = R.string.apn_edit),
actions = {
if (!apnData.customizedConfig.readOnlyApn) {
IconButton(onClick = {
if (!apnData.validEnabled) apnData = apnData.copy(validEnabled = true)
val valid = validateAndSaveApnData(
Button(onClick = {
apnData = apnData.copy(
networkType = ApnNetworkTypes.getNetworkType(
networkTypeSelectedOptionsState
)
)
valid = validateAndSaveApnData(
apnDataInit,
apnData,
context,
uriInit,
networkTypeSelectedOptionsState
uriInit
)
if (valid) navController.navigateBack()
}) { Icon(imageVector = Icons.Outlined.Done, contentDescription = null) }
if (valid == null) navController.navigateBack()
else if (!apnData.validEnabled) apnData = apnData.copy(validEnabled = true)
}) { Text(text = stringResource(id = R.string.save)) }
}
if (!apnData.newApn && !apnData.customizedConfig.readOnlyApn
&& apnData.customizedConfig.isAddApnAllowed
) {
MoreOptionsAction {
DropdownMenuItem(
text = { Text(stringResource(R.string.menu_delete)) },
onClick = {
deleteApn(uriInit, context)
navController.navigateBack()
})
}
}
},
) {
Column {
if (apnData.validEnabled) {
apnData = apnData.copy(
networkType = ApnNetworkTypes.getNetworkType(
networkTypeSelectedOptionsState
)
)
valid = validateApnData(uriInit, apnData, context)
valid?.let {
Text(
text = it,
modifier = Modifier
.fillMaxWidth()
.padding(SettingsDimension.menuFieldPadding),
color = MaterialTheme.colorScheme.primary
)
}
}
SettingsOutlinedTextField(
value = apnData.name,
label = stringResource(R.string.apn_name),
@@ -214,19 +251,6 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur
emptyVal = stringResource(R.string.network_type_unspecified),
enabled = apnData.networkTypeEnabled
) {}
if (!apnData.newApn && !apnData.customizedConfig.readOnlyApn
&& apnData.customizedConfig.isAddApnAllowed
) {
Preference(
object : PreferenceModel {
override val title = stringResource(R.string.menu_delete)
override val onClick = {
deleteApn(uriInit, context)
navController.navigateBack()
}
}
)
}
}
}
}

View File

@@ -20,6 +20,7 @@ import android.content.ContentValues
import android.content.Context
import android.net.Uri
import android.provider.Telephony
import android.telephony.TelephonyManager
import android.util.Log
import com.android.settings.R
import com.android.settingslib.utils.ThreadUtils
@@ -150,7 +151,6 @@ fun getApnDataFromUri(uri: Uri, context: Context): ApnData {
private fun convertProtocol2Options(raw: String, context: Context): String {
val apnProtocolOptions = context.resources.getStringArray(R.array.apn_protocol_entries).toList()
val apnProtocolValues = context.resources.getStringArray(R.array.apn_protocol_values).toList()
var uRaw = raw.uppercase(Locale.getDefault())
uRaw = if (uRaw == "IPV4") "IP" else uRaw
val protocolIndex = apnProtocolValues.indexOf(uRaw)
@@ -167,7 +167,6 @@ private fun convertProtocol2Options(raw: String, context: Context): String {
fun convertOptions2Protocol(protocolIndex: Int, context: Context): String {
val apnProtocolValues = context.resources.getStringArray(R.array.apn_protocol_values).toList()
return if (protocolIndex == -1) {
""
} else {
@@ -179,7 +178,12 @@ fun convertOptions2Protocol(protocolIndex: Int, context: Context): String {
}
}
fun updateApnDataToDatabase(newApn: Boolean, values: ContentValues, context: Context, uriInit: Uri) {
fun updateApnDataToDatabase(
newApn: Boolean,
values: ContentValues,
context: Context,
uriInit: Uri
) {
ThreadUtils.postOnBackgroundThread {
if (newApn) {
// Add a new apn to the database
@@ -194,4 +198,24 @@ fun updateApnDataToDatabase(newApn: Boolean, values: ContentValues, context: Con
)
}
}
}
fun isItemExist(uri: Uri, apnData: ApnData, context: Context): String? {
val contentValueMap = apnData.getContentValueMap(context)
contentValueMap.remove(Telephony.Carriers.CARRIER_ENABLED)
val list = contentValueMap.entries.toList()
val selection = list.joinToString(" AND ") { "${it.key} = ?" }
val selectionArgs: Array<String> = list.map { it.value.toString() }.toTypedArray()
context.contentResolver.query(
uri,
sProjection,
selection /* selection */,
selectionArgs /* selectionArgs */,
null /* sortOrder */
)?.use { cursor ->
if (cursor.count > 0) {
return context.resources.getString(R.string.error_duplicate_apn_entry)
}
}
return null
}

View File

@@ -72,41 +72,38 @@ data class ApnData(
val validEnabled: Boolean = false,
val customizedConfig: CustomizedConfig = CustomizedConfig()
) {
fun getContentValueMap(context: Context): MutableMap<String, Any> {
val simCarrierId =
context.getSystemService(TelephonyManager::class.java)!!
.createForSubscriptionId(subId)
.getSimCarrierId()
return mutableMapOf(
Telephony.Carriers.NAME to name, Telephony.Carriers.APN to apn,
Telephony.Carriers.PROXY to proxy, Telephony.Carriers.PORT to port,
Telephony.Carriers.MMSPROXY to mmsProxy, Telephony.Carriers.MMSPORT to mmsPort,
Telephony.Carriers.USER to userName, Telephony.Carriers.SERVER to server,
Telephony.Carriers.PASSWORD to passWord, Telephony.Carriers.MMSC to mmsc,
Telephony.Carriers.AUTH_TYPE to authType,
Telephony.Carriers.PROTOCOL to convertOptions2Protocol(apnProtocol, context),
Telephony.Carriers.ROAMING_PROTOCOL to convertOptions2Protocol(apnRoaming, context),
Telephony.Carriers.TYPE to apnType,
Telephony.Carriers.NETWORK_TYPE_BITMASK to networkType,
Telephony.Carriers.CARRIER_ENABLED to apnEnable,
Telephony.Carriers.EDITED_STATUS to Telephony.Carriers.USER_EDITED,
Telephony.Carriers.CARRIER_ID to simCarrierId
)
}
fun getContentValues(context: Context): ContentValues {
val values = ContentValues()
values.put(Telephony.Carriers.NAME, name)
values.put(Telephony.Carriers.APN, apn)
values.put(Telephony.Carriers.PROXY, proxy)
values.put(Telephony.Carriers.PORT, port)
values.put(Telephony.Carriers.MMSPROXY, mmsProxy)
values.put(Telephony.Carriers.MMSPORT, mmsPort)
values.put(Telephony.Carriers.USER, userName)
values.put(Telephony.Carriers.SERVER, server)
values.put(Telephony.Carriers.PASSWORD, passWord)
values.put(Telephony.Carriers.MMSC, mmsc)
values.put(Telephony.Carriers.AUTH_TYPE, authType)
values.put(Telephony.Carriers.PROTOCOL, convertOptions2Protocol(apnProtocol, context))
values.put(
Telephony.Carriers.ROAMING_PROTOCOL,
convertOptions2Protocol(apnRoaming, context)
)
values.put(Telephony.Carriers.TYPE, apnType)
values.put(Telephony.Carriers.NETWORK_TYPE_BITMASK, networkType)
values.put(Telephony.Carriers.CARRIER_ENABLED, apnEnable)
values.put(Telephony.Carriers.EDITED_STATUS, Telephony.Carriers.USER_EDITED)
if (newApn) {
val simCarrierId =
context.getSystemService(TelephonyManager::class.java)!!
.createForSubscriptionId(subId)
.getSimCarrierId()
values.put(Telephony.Carriers.CARRIER_ID, simCarrierId)
}
val contentValueMap = getContentValueMap(context)
if (!newApn) contentValueMap.remove(Telephony.Carriers.CARRIER_ID)
contentValueMap.forEach { (key, value) -> values.putObject(key, value) }
return values
}
}
data class CustomizedConfig(
val newApn: Boolean = false,
val readOnlyApn: Boolean = false,
val isAddApnAllowed: Boolean = true,
val readOnlyApnTypes: List<String> = emptyList(),
@@ -227,20 +224,14 @@ fun getApnDataInit(arguments: Bundle, context: Context, uriInit: Uri, subId: Int
*/
fun validateAndSaveApnData(
apnDataInit: ApnData,
apnData: ApnData,
newApnData: ApnData,
context: Context,
uriInit: Uri,
networkTypeSelectedOptionsState: SnapshotStateList<Int>
): Boolean {
// Nothing to do if it's a read only APN
if (apnData.customizedConfig.readOnlyApn) {
return true
}
val errorMsg = validateApnData(apnData, context)
uriInit: Uri
): String? {
val errorMsg = validateApnData(uriInit, newApnData, context)
if (errorMsg != null) {
return false
return errorMsg
}
val newApnData = apnData.copy(networkType = getNetworkType(networkTypeSelectedOptionsState))
if (newApnData.newApn || (newApnData != apnDataInit)) {
Log.d(TAG, "[validateAndSaveApnData] newApnData.networkType: ${newApnData.networkType}")
updateApnDataToDatabase(
@@ -250,7 +241,7 @@ fun validateAndSaveApnData(
uriInit
)
}
return true
return null
}
/**
@@ -258,7 +249,7 @@ fun validateAndSaveApnData(
*
* @return An error message if the apn data is invalid, otherwise return null.
*/
fun validateApnData(apnData: ApnData, context: Context): String? {
fun validateApnData(uri: Uri, apnData: ApnData, context: Context): String? {
var errorMsg: String?
val name = apnData.name
val apn = apnData.apn
@@ -267,11 +258,14 @@ fun validateApnData(apnData: ApnData, context: Context): String? {
} else if (apn == "") {
context.resources.getString(R.string.error_apn_empty)
} else {
validateMMSC(apnData.validEnabled, apnData.mmsc, context)
validateMMSC(true, apnData.mmsc, context)
}
if (errorMsg == null) {
errorMsg = isItemExist(uri, apnData, context)
}
if (errorMsg == null) {
errorMsg = validateAPNType(
apnData.validEnabled,
true,
apnData.apnType,
apnData.customizedConfig.readOnlyApnTypes,
context

View File

@@ -104,7 +104,7 @@ class AppArchiveButton(
userHandle
)
try {
packageInstaller.requestArchive(app.packageName, pendingIntent.intentSender, 0)
packageInstaller.requestArchive(app.packageName, pendingIntent.intentSender)
} catch (e: Exception) {
Log.e(LOG_TAG, "Request archive failed", e)
Toast.makeText(

View File

@@ -56,9 +56,12 @@ class VoiceActivationAppsListModel(context: Context) : AppOpPermissionListModel(
override val appOp = AppOpsManager.OP_RECEIVE_SANDBOX_TRIGGER_AUDIO
override val permission = Manifest.permission.RECEIVE_SANDBOX_TRIGGER_AUDIO
override val setModeByUid = true
private var receiveDetectionTrainingDataOpController:AppOpsController? = null
override fun setAllowed(record: AppOpPermissionRecord, newAllowed: Boolean) {
super.setAllowed(record, newAllowed)
if (!newAllowed && receiveDetectionTrainingDataOpController != null) {
receiveDetectionTrainingDataOpController!!.setAllowed(false)
}
logPermissionChange(newAllowed)
}
@@ -79,20 +82,21 @@ class VoiceActivationAppsListModel(context: Context) : AppOpPermissionListModel(
isReceiveSandBoxTriggerAudioOpAllowed: () -> Boolean?
): ReceiveDetectionTrainingDataOpSwitchModel {
val context = LocalContext.current
val ReceiveDetectionTrainingDataOpController = remember {
receiveDetectionTrainingDataOpController = remember {
AppOpsController(
context = context,
app = record.app,
op = AppOpsManager.OP_RECEIVE_SANDBOXED_DETECTION_TRAINING_DATA,
)
}
val isReceiveDetectionTrainingDataOpAllowed = isReceiveDetectionTrainingDataOpAllowed(record, ReceiveDetectionTrainingDataOpController)
val isReceiveDetectionTrainingDataOpAllowed = isReceiveDetectionTrainingDataOpAllowed(record, receiveDetectionTrainingDataOpController!!)
return remember(record) {
ReceiveDetectionTrainingDataOpSwitchModel(
context,
record,
isReceiveSandBoxTriggerAudioOpAllowed,
ReceiveDetectionTrainingDataOpController,
receiveDetectionTrainingDataOpController!!,
isReceiveDetectionTrainingDataOpAllowed,
)
}.also { model -> LaunchedEffect(model, Dispatchers.Default) { model.initState() } }

View File

@@ -28,6 +28,7 @@ import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.preference.Preference;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.Settings;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.factory_reset.Flags;
@@ -36,11 +37,14 @@ public class FactoryResetPreferenceController extends BasePreferenceController {
private static final String TAG = "FactoryResetPreference";
private static final String ACTION_PREPARE_FACTORY_RESET =
@VisibleForTesting
static final String ACTION_PREPARE_FACTORY_RESET =
"com.android.settings.ACTION_PREPARE_FACTORY_RESET";
private final UserManager mUm;
private ActivityResultLauncher<Intent> mFactoryResetPreparationLauncher;
@VisibleForTesting
ActivityResultLauncher<Intent> mFactoryResetPreparationLauncher;
public FactoryResetPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);

View File

@@ -17,75 +17,125 @@ package com.android.settings.system;
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.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.provider.Settings;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settings.testutils.shadow.ShadowUtils;
import androidx.activity.result.ActivityResultLauncher;
import androidx.preference.Preference;
import com.google.common.collect.ImmutableList;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowUserManager.class)
public class FactoryResetPreferenceControllerTest {
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
private static final String FACTORY_RESET_KEY = "factory_reset";
private static final String FACTORY_RESET_APP_PACKAGE = "com.frw_app";
private ShadowUserManager mShadowUserManager;
@Mock private ActivityResultLauncher<Intent> mFactoryResetLauncher;
@Mock private Preference mPreference;
@Mock private Context mContext;
@Mock private PackageManager mPackageManager;
@Mock private UserManager mUserManager;
private ResolveInfo mFactoryResetAppResolveInfo;
private PackageInfo mFactoryResetAppPackageInfo;
private Context mContext;
private FactoryResetPreferenceController mController;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mShadowUserManager = ShadowUserManager.getShadow();
public void setUp() throws PackageManager.NameNotFoundException {
MockitoAnnotations.initMocks(this);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mController = new FactoryResetPreferenceController(mContext, FACTORY_RESET_KEY);
mFactoryResetAppResolveInfo = new ResolveInfo();
mFactoryResetAppResolveInfo.activityInfo = new ActivityInfo();
mFactoryResetAppResolveInfo.activityInfo.packageName = FACTORY_RESET_APP_PACKAGE;
mFactoryResetAppPackageInfo = new PackageInfo();
mFactoryResetAppPackageInfo.requestedPermissions =
new String[] {Manifest.permission.PREPARE_FACTORY_RESET};
mFactoryResetAppPackageInfo.requestedPermissionsFlags = new int[] {
PackageInfo.REQUESTED_PERMISSION_GRANTED
};
when(mPackageManager.resolveActivity(any(), anyInt()))
.thenReturn(mFactoryResetAppResolveInfo);
when(mPackageManager.getPackageInfo(anyString(), anyInt()))
.thenReturn(mFactoryResetAppPackageInfo);
when(mPreference.getKey()).thenReturn(FACTORY_RESET_KEY);
mController.mFactoryResetPreparationLauncher = mFactoryResetLauncher;
}
@After
public void tearDown() {
ShadowUtils.reset();
mShadowUserManager.setIsAdminUser(false);
mShadowUserManager.setIsDemoUser(false);
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_DEMO_MODE, 0);
Mockito.reset(mUserManager, mPackageManager);
Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
Settings.Global.DEVICE_DEMO_MODE, 0);
}
@Ignore("b/314930928")
@Test
public void isAvailable_systemUser() {
mShadowUserManager.setIsAdminUser(true);
when(mUserManager.isAdminUser()).thenReturn(true);
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void isAvailable_nonSystemUser() {
mShadowUserManager.setIsAdminUser(false);
mShadowUserManager.setIsDemoUser(false);
when(mUserManager.isAdminUser()).thenReturn(false);
when(mUserManager.isDemoUser()).thenReturn(false);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_demoUser() {
mShadowUserManager.setIsAdminUser(false);
when(mUserManager.isAdminUser()).thenReturn(false);
// Place the device in demo mode.
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_DEMO_MODE, 1);
Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
Settings.Global.DEVICE_DEMO_MODE, 1);
// Indicate the user is a demo user.
mShadowUserManager.addUser(UserHandle.myUserId(), "test", UserInfo.FLAG_DEMO);
when(mUserManager.getUserProfiles())
.thenReturn(ImmutableList.of(new UserHandle(UserHandle.myUserId())));
when(mUserManager.getUserInfo(eq(UserHandle.myUserId())))
.thenReturn(new UserInfo(UserHandle.myUserId(), "test", UserInfo.FLAG_DEMO));
assertThat(mController.isAvailable()).isFalse();
}
@@ -94,4 +144,16 @@ public class FactoryResetPreferenceControllerTest {
public void getPreferenceKey() {
assertThat(mController.getPreferenceKey()).isEqualTo(FACTORY_RESET_KEY);
}
@Test
@RequiresFlagsEnabled(com.android.settings.factory_reset.Flags.FLAG_ENABLE_FACTORY_RESET_WIZARD)
public void handlePreference_factoryResetWizardEnabled() {
ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
verify(mFactoryResetLauncher).launch(intentArgumentCaptor.capture());
assertThat(intentArgumentCaptor.getValue()).isNotNull();
assertThat(intentArgumentCaptor.getValue().getAction())
.isEqualTo(FactoryResetPreferenceController.ACTION_PREPARE_FACTORY_RESET);
}
}

View File

@@ -16,7 +16,6 @@
package com.android.settings.testutils.shadow;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
@@ -25,7 +24,7 @@ import java.util.HashMap;
import java.util.Map;
@Implements(android.provider.DeviceConfig.class)
public class ShadowDeviceConfig {
public class ShadowDeviceConfig extends org.robolectric.shadows.ShadowDeviceConfig {
private static Map<String, String> sPropertyMaps = new HashMap<>();

View File

@@ -136,8 +136,7 @@ class AppArchiveButtonTest {
verify(packageInstaller).requestArchive(
eq(PACKAGE_NAME),
any(),
eq(0)
any()
)
}