Snap for 10078820 from 17a0266b16 to udc-release

Change-Id: I9e5dab9eaa426371cdc64e4e517846863d1cafe8
This commit is contained in:
Android Build Coastguard Worker
2023-05-06 01:32:32 +00:00
21 changed files with 431 additions and 116 deletions

View File

@@ -17,9 +17,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:viewportWidth="24.0" android:viewportWidth="960"
android:viewportHeight="24.0"> android:viewportHeight="960">
<path <path
android:pathData="M20,6h-4L16,4c0,-1.11 -0.89,-2 -2,-2h-4c-1.11,0 -2,0.89 -2,2v2L4,6c-1.11,0 -1.99,0.89 -1.99,2L2,19c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2L22,8c0,-1.11 -0.89,-2 -2,-2zM12,15c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM14,6h-4L10,4h4v2z" android:pathData="M140,840Q116,840 98,822Q80,804 80,780L80,300Q80,276 98,258Q116,240 140,240L320,240L320,140Q320,116 338,98Q356,80 380,80L580,80Q604,80 622,98Q640,116 640,140L640,240L820,240Q844,240 862,258Q880,276 880,300L880,780Q880,804 862,822Q844,840 820,840L140,840ZM380,240L580,240L580,140Q580,140 580,140Q580,140 580,140L380,140Q380,140 380,140Q380,140 380,140L380,240Z"
android:fillColor="?android:attr/colorPrimary"/> android:fillColor="?android:attr/colorPrimary"/>
</vector> </vector>

View File

@@ -0,0 +1,26 @@
<!--
~ Copyright (C) 2023 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="960"
android:viewportHeight="960"
android:tint="?android:attr/colorControlNormal">
<path android:fillColor="@android:color/white"
android:pathData="M167,840Q146,845 130.5,829.5Q115,814 120,793L160,602L358,800L167,840ZM358,800L160,602L618,144Q641,121 675,121Q709,121 732,144L816,228Q839,251 839,285Q839,319 816,342L358,800ZM675,200L261,614L346,699L760,285Q760,285 760,285Q760,285 760,285L675,200Q675,200 675,200Q675,200 675,200Z"/>
</vector>

View File

@@ -43,18 +43,22 @@ public final class CombinedProviderInfo {
private final List<CredentialProviderInfo> mCredentialProviderInfos; private final List<CredentialProviderInfo> mCredentialProviderInfos;
private final @Nullable AutofillServiceInfo mAutofillServiceInfo; private final @Nullable AutofillServiceInfo mAutofillServiceInfo;
private final boolean mIsDefaultAutofillProvider; private final boolean mIsDefaultAutofillProvider;
private final boolean mIsDefaultCredmanProvider; private final boolean mIsPrimaryCredmanProvider;
/** Constructs an information instance from both autofill and credential provider. */ /** Constructs an information instance from both autofill and credential provider. */
public CombinedProviderInfo( public CombinedProviderInfo(
@Nullable List<CredentialProviderInfo> cpis, @Nullable List<CredentialProviderInfo> cpis,
@Nullable AutofillServiceInfo asi, @Nullable AutofillServiceInfo asi,
boolean isDefaultAutofillProvider, boolean isDefaultAutofillProvider,
boolean isDefaultCredmanProvider) { boolean IsPrimaryCredmanProvider) {
mCredentialProviderInfos = new ArrayList<>(cpis); if (cpis == null) {
mCredentialProviderInfos = new ArrayList<>();
} else {
mCredentialProviderInfos = new ArrayList<>(cpis);
}
mAutofillServiceInfo = asi; mAutofillServiceInfo = asi;
mIsDefaultAutofillProvider = isDefaultAutofillProvider; mIsDefaultAutofillProvider = isDefaultAutofillProvider;
mIsDefaultCredmanProvider = isDefaultCredmanProvider; mIsPrimaryCredmanProvider = IsPrimaryCredmanProvider;
} }
/** Returns the credential provider info. */ /** Returns the credential provider info. */
@@ -149,8 +153,8 @@ public final class CombinedProviderInfo {
} }
/** Returns whether the provider is the default credman provider. */ /** Returns whether the provider is the default credman provider. */
public boolean isDefaultCredmanProvider() { public boolean isPrimaryCredmanProvider() {
return mIsDefaultCredmanProvider; return mIsPrimaryCredmanProvider;
} }
/** Returns the settings subtitle. */ /** Returns the settings subtitle. */
@@ -192,7 +196,13 @@ public final class CombinedProviderInfo {
} }
} }
// TODO(280454916): Add logic here. // If there is a primary cred man provider then return that.
for (CombinedProviderInfo cpi : providers) {
if (cpi.isPrimaryCredmanProvider()) {
return cpi;
}
}
return null; return null;
} }
@@ -250,14 +260,14 @@ public final class CombinedProviderInfo {
} }
// Check if we have any enabled cred man services. // Check if we have any enabled cred man services.
boolean isDefaultCredmanProvider = false; boolean isPrimaryCredmanProvider = false;
if (!cpi.isEmpty()) { if (cpi != null && !cpi.isEmpty()) {
isDefaultCredmanProvider = cpi.get(0).isEnabled(); isPrimaryCredmanProvider = cpi.get(0).isPrimary();
} }
cmpi.add( cmpi.add(
new CombinedProviderInfo( new CombinedProviderInfo(
cpi, selectedAsi, isDefaultAutofillProvider, isDefaultCredmanProvider)); cpi, selectedAsi, isDefaultAutofillProvider, isPrimaryCredmanProvider));
} }
return cmpi; return cmpi;

View File

@@ -120,6 +120,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
mCredentialManager = mCredentialManager =
getCredentialManager(context, preferenceKey.equals("credentials_test")); getCredentialManager(context, preferenceKey.equals("credentials_test"));
new SettingContentObserver(mHandler).register(context.getContentResolver()); new SettingContentObserver(mHandler).register(context.getContentResolver());
mSettingsPackageMonitor.register(context, context.getMainLooper(), false);
} }
private @Nullable CredentialManager getCredentialManager(Context context, boolean isTest) { private @Nullable CredentialManager getCredentialManager(Context context, boolean isTest) {
@@ -321,7 +322,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
mEnabledPackageNames.clear(); mEnabledPackageNames.clear();
for (CredentialProviderInfo cpi : availableServices) { for (CredentialProviderInfo cpi : availableServices) {
if (cpi.isEnabled()) { if (cpi.isEnabled() && !cpi.isPrimary()) {
mEnabledPackageNames.add(cpi.getServiceInfo().packageName); mEnabledPackageNames.add(cpi.getServiceInfo().packageName);
} }
} }
@@ -560,15 +561,25 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
return; return;
} }
List<String> enabledServices = getEnabledSettings(); // Get the existing primary providers since we don't touch them in
// this part of the UI we should just copy them over.
Set<String> primaryServices = new HashSet<>();
for (CredentialProviderInfo service : mServices) {
if (service.isPrimary()) {
primaryServices.add(service.getServiceInfo().getComponentName().flattenToString());
}
}
mCredentialManager.setEnabledProviders( mCredentialManager.setEnabledProviders(
enabledServices, new ArrayList<>(primaryServices),
getEnabledSettings(),
getUser(), getUser(),
mExecutor, mExecutor,
new OutcomeReceiver<Void, SetEnabledProvidersException>() { new OutcomeReceiver<Void, SetEnabledProvidersException>() {
@Override @Override
public void onResult(Void result) { public void onResult(Void result) {
Log.i(TAG, "setEnabledProviders success"); Log.i(TAG, "setEnabledProviders success");
updateFromExternal();
} }
@Override @Override

View File

@@ -47,7 +47,9 @@ import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.widget.CandidateInfo; import com.android.settingslib.widget.CandidateInfo;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
public class DefaultCombinedPicker extends DefaultAppPickerFragment { public class DefaultCombinedPicker extends DefaultAppPickerFragment {
@@ -338,9 +340,9 @@ public class DefaultCombinedPicker extends DefaultAppPickerFragment {
return true; return true;
} }
private void setProviders(String autofillProvider, List<String> credManProviders) { private void setProviders(String autofillProvider, List<String> primaryCredManProviders) {
if (TextUtils.isEmpty(autofillProvider)) { if (TextUtils.isEmpty(autofillProvider)) {
if (credManProviders.size() > 0) { if (primaryCredManProviders.size() > 0) {
autofillProvider = autofillProvider =
CredentialManagerPreferenceController CredentialManagerPreferenceController
.AUTOFILL_CREDMAN_ONLY_PROVIDER_PLACEHOLDER; .AUTOFILL_CREDMAN_ONLY_PROVIDER_PLACEHOLDER;
@@ -350,12 +352,25 @@ public class DefaultCombinedPicker extends DefaultAppPickerFragment {
Settings.Secure.putStringForUser( Settings.Secure.putStringForUser(
getContext().getContentResolver(), AUTOFILL_SETTING, autofillProvider, mUserId); getContext().getContentResolver(), AUTOFILL_SETTING, autofillProvider, mUserId);
CredentialManager service = getCredentialProviderService(); final CredentialManager service = getCredentialProviderService();
if (service == null) { if (service == null) {
return; return;
} }
// Get the existing secondary providers since we don't touch them in
// this part of the UI we should just copy them over.
final List<String> credManProviders = new ArrayList<>();
for (CredentialProviderInfo cpi :
service.getCredentialProviderServices(
mUserId, CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY)) {
if (cpi.isEnabled()) {
credManProviders.add(cpi.getServiceInfo().getComponentName().flattenToString());
}
}
service.setEnabledProviders( service.setEnabledProviders(
primaryCredManProviders,
credManProviders, credManProviders,
mUserId, mUserId,
ContextCompat.getMainExecutor(getContext()), ContextCompat.getMainExecutor(getContext()),

View File

@@ -135,12 +135,12 @@ public class DefaultCombinedPreferenceController extends DefaultAppPreferenceCon
/** Provides Intent to setting activity for the specified autofill service. */ /** Provides Intent to setting activity for the specified autofill service. */
static final class AutofillSettingIntentProvider { static final class AutofillSettingIntentProvider {
private final String mSelectedKey; private final String mKey;
private final Context mContext; private final Context mContext;
private final int mUserId; private final int mUserId;
public AutofillSettingIntentProvider(Context context, int userId, String key) { public AutofillSettingIntentProvider(Context context, int userId, String key) {
mSelectedKey = key; mKey = key;
mContext = context; mContext = context;
mUserId = userId; mUserId = userId;
} }
@@ -153,10 +153,9 @@ public class DefaultCombinedPreferenceController extends DefaultAppPreferenceCon
for (ResolveInfo resolveInfo : resolveInfos) { for (ResolveInfo resolveInfo : resolveInfos) {
final ServiceInfo serviceInfo = resolveInfo.serviceInfo; final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
final String flattenKey =
new ComponentName(serviceInfo.packageName, serviceInfo.name) // If there are multiple autofill services then pick the first one.
.flattenToString(); if (mKey.startsWith(serviceInfo.packageName)) {
if (TextUtils.equals(mSelectedKey, flattenKey)) {
final String settingsActivity; final String settingsActivity;
try { try {
settingsActivity = settingsActivity =
@@ -164,7 +163,7 @@ public class DefaultCombinedPreferenceController extends DefaultAppPreferenceCon
.getSettingsActivity(); .getSettingsActivity();
} catch (SecurityException e) { } catch (SecurityException e) {
// Service does not declare the proper permission, ignore it. // Service does not declare the proper permission, ignore it.
Log.w(TAG, "Error getting info for " + serviceInfo + ": " + e); Log.e(TAG, "Error getting info for " + serviceInfo + ": " + e);
return null; return null;
} }
if (TextUtils.isEmpty(settingsActivity)) { if (TextUtils.isEmpty(settingsActivity)) {

View File

@@ -72,6 +72,7 @@ public class RequestPermissionActivity extends Activity implements
private int mRequest; private int mRequest;
private AlertDialog mDialog; private AlertDialog mDialog;
private AlertDialog mRequestDialog;
private BroadcastReceiver mReceiver; private BroadcastReceiver mReceiver;
@@ -96,33 +97,35 @@ public class RequestPermissionActivity extends Activity implements
if (mRequest == REQUEST_DISABLE) { if (mRequest == REQUEST_DISABLE) {
switch (btState) { switch (btState) {
case BluetoothAdapter.STATE_OFF: case BluetoothAdapter.STATE_OFF:
case BluetoothAdapter.STATE_TURNING_OFF: { case BluetoothAdapter.STATE_TURNING_OFF:
proceedAndFinish(); proceedAndFinish();
} break; break;
case BluetoothAdapter.STATE_ON: case BluetoothAdapter.STATE_ON:
case BluetoothAdapter.STATE_TURNING_ON: { case BluetoothAdapter.STATE_TURNING_ON:
RequestPermissionHelper.INSTANCE.requestDisable(this, mAppLabel, mRequestDialog =
() -> { RequestPermissionHelper.INSTANCE.requestDisable(this, mAppLabel,
onDisableConfirmed(); () -> {
return Unit.INSTANCE; onDisableConfirmed();
}, return Unit.INSTANCE;
() -> { },
cancelAndFinish(); () -> {
return Unit.INSTANCE; cancelAndFinish();
}); return Unit.INSTANCE;
} break; });
if (mRequestDialog != null) {
default: { mRequestDialog.show();
}
break;
default:
Log.e(TAG, "Unknown adapter state: " + btState); Log.e(TAG, "Unknown adapter state: " + btState);
cancelAndFinish(); cancelAndFinish();
} break; break;
} }
} else { } else {
switch (btState) { switch (btState) {
case BluetoothAdapter.STATE_OFF: case BluetoothAdapter.STATE_OFF:
case BluetoothAdapter.STATE_TURNING_OFF: case BluetoothAdapter.STATE_TURNING_OFF:
case BluetoothAdapter.STATE_TURNING_ON: { case BluetoothAdapter.STATE_TURNING_ON:
/* /*
* Strictly speaking STATE_TURNING_ON belong with STATE_ON; * Strictly speaking STATE_TURNING_ON belong with STATE_ON;
* however, BT may not be ready when the user clicks yes and we * however, BT may not be ready when the user clicks yes and we
@@ -131,20 +134,23 @@ public class RequestPermissionActivity extends Activity implements
* case via the broadcast receiver. * case via the broadcast receiver.
*/ */
// Start the helper activity to ask the user about enabling bt AND discovery // Show the helper dialog to ask the user about enabling bt AND discovery
RequestPermissionHelper.INSTANCE.requestEnable(this, mAppLabel, mRequestDialog =
mRequest == REQUEST_ENABLE_DISCOVERABLE ? mTimeout : -1, RequestPermissionHelper.INSTANCE.requestEnable(this, mAppLabel,
() -> { mRequest == REQUEST_ENABLE_DISCOVERABLE ? mTimeout : -1,
onEnableConfirmed(); () -> {
return Unit.INSTANCE; onEnableConfirmed();
}, return Unit.INSTANCE;
() -> { },
cancelAndFinish(); () -> {
return Unit.INSTANCE; cancelAndFinish();
}); return Unit.INSTANCE;
} break; });
if (mRequestDialog != null) {
case BluetoothAdapter.STATE_ON: { mRequestDialog.show();
}
break;
case BluetoothAdapter.STATE_ON:
if (mRequest == REQUEST_ENABLE) { if (mRequest == REQUEST_ENABLE) {
// Nothing to do. Already enabled. // Nothing to do. Already enabled.
proceedAndFinish(); proceedAndFinish();
@@ -152,12 +158,11 @@ public class RequestPermissionActivity extends Activity implements
// Ask the user about enabling discovery mode // Ask the user about enabling discovery mode
createDialog(); createDialog();
} }
} break; break;
default:
default: {
Log.e(TAG, "Unknown adapter state: " + btState); Log.e(TAG, "Unknown adapter state: " + btState);
cancelAndFinish(); cancelAndFinish();
} break; break;
} }
} }
} }
@@ -275,10 +280,6 @@ public class RequestPermissionActivity extends Activity implements
} }
} }
if (mDialog != null) {
mDialog.dismiss();
}
setResult(returnCode); setResult(returnCode);
finish(); finish();
} }
@@ -365,6 +366,14 @@ public class RequestPermissionActivity extends Activity implements
unregisterReceiver(mReceiver); unregisterReceiver(mReceiver);
mReceiver = null; mReceiver = null;
} }
if (mDialog != null && mDialog.isShowing()) {
mDialog.dismiss();
mDialog = null;
}
if (mRequestDialog != null && mRequestDialog.isShowing()) {
mRequestDialog.dismiss();
mRequestDialog = null;
}
} }
@Override @Override

View File

@@ -30,20 +30,20 @@ object RequestPermissionHelper {
timeout: Int, timeout: Int,
onAllow: () -> Unit, onAllow: () -> Unit,
onDeny: () -> Unit, onDeny: () -> Unit,
) { ): AlertDialog? {
if (context.resources.getBoolean(R.bool.auto_confirm_bluetooth_activation_dialog)) { if (context.resources.getBoolean(R.bool.auto_confirm_bluetooth_activation_dialog)) {
// Don't even show the dialog if configured this way // Don't even show the dialog if configured this way
onAllow() onAllow()
return return null
} }
AlertDialog.Builder(context).apply { return AlertDialog.Builder(context).apply {
setMessage(context.getEnableMessage(timeout, appLabel)) setMessage(context.getEnableMessage(timeout, appLabel))
setPositiveButton(R.string.allow) { _, _ -> setPositiveButton(R.string.allow) { _, _ ->
if (context.isDisallowBluetooth()) onDeny() else onAllow() if (context.isDisallowBluetooth()) onDeny() else onAllow()
} }
setNegativeButton(R.string.deny) { _, _ -> onDeny() } setNegativeButton(R.string.deny) { _, _ -> onDeny() }
setOnCancelListener { onDeny() } setOnCancelListener { onDeny() }
}.show() }.create()
} }
fun requestDisable( fun requestDisable(
@@ -51,18 +51,18 @@ object RequestPermissionHelper {
appLabel: CharSequence?, appLabel: CharSequence?,
onAllow: () -> Unit, onAllow: () -> Unit,
onDeny: () -> Unit, onDeny: () -> Unit,
) { ): AlertDialog? {
if (context.resources.getBoolean(R.bool.auto_confirm_bluetooth_activation_dialog)) { if (context.resources.getBoolean(R.bool.auto_confirm_bluetooth_activation_dialog)) {
// Don't even show the dialog if configured this way // Don't even show the dialog if configured this way
onAllow() onAllow()
return return null
} }
AlertDialog.Builder(context).apply { return AlertDialog.Builder(context).apply {
setMessage(context.getDisableMessage(appLabel)) setMessage(context.getDisableMessage(appLabel))
setPositiveButton(R.string.allow) { _, _ -> onAllow() } setPositiveButton(R.string.allow) { _, _ -> onAllow() }
setNegativeButton(R.string.deny) { _, _ -> onDeny() } setNegativeButton(R.string.deny) { _, _ -> onDeny() }
setOnCancelListener { onDeny() } setOnCancelListener { onDeny() }
}.show() }.create()
} }
} }

View File

@@ -165,8 +165,7 @@ public class StylusDeviceUpdater implements InputManager.InputDeviceListener,
} }
mUsiPreference.setKey(PREF_KEY); mUsiPreference.setKey(PREF_KEY);
mUsiPreference.setTitle(R.string.stylus_connected_devices_title); mUsiPreference.setTitle(R.string.stylus_connected_devices_title);
// TODO(b/250909304): pending actual icon visD mUsiPreference.setIcon(R.drawable.ic_stylus);
mUsiPreference.setIcon(R.drawable.ic_edit);
mUsiPreference.setOnPreferenceClickListener((Preference p) -> { mUsiPreference.setOnPreferenceClickListener((Preference p) -> {
mMetricsFeatureProvider.logClickedPreference(p, mFragment.getMetricsCategory()); mMetricsFeatureProvider.logClickedPreference(p, mFragment.getMetricsCategory());
launchDeviceDetails(); launchDeviceDetails();

View File

@@ -70,8 +70,7 @@ public class StylusUsiHeaderController extends BasePreferenceController implemen
ImageView iconView = mHeaderPreference.findViewById(R.id.entity_header_icon); ImageView iconView = mHeaderPreference.findViewById(R.id.entity_header_icon);
if (iconView != null) { if (iconView != null) {
// TODO(b/250909304): get proper icon once VisD ready iconView.setImageResource(R.drawable.ic_stylus);
iconView.setImageResource(R.drawable.ic_edit);
iconView.setContentDescription("Icon for stylus"); iconView.setContentDescription("Icon for stylus");
} }
refresh(); refresh();

View File

@@ -30,12 +30,12 @@ public class TrackpadReverseScrollingPreferenceController extends TogglePreferen
@Override @Override
public boolean isChecked() { public boolean isChecked() {
return InputSettings.useTouchpadNaturalScrolling(mContext); return !InputSettings.useTouchpadNaturalScrolling(mContext);
} }
@Override @Override
public boolean setChecked(boolean isChecked) { public boolean setChecked(boolean isChecked) {
InputSettings.setTouchpadNaturalScrolling(mContext, isChecked); InputSettings.setTouchpadNaturalScrolling(mContext, !isChecked);
return true; return true;
} }

View File

@@ -22,14 +22,34 @@ import android.content.Intent
import android.os.RemoteException import android.os.RemoteException
import android.os.UserHandle import android.os.UserHandle
import android.util.Log import android.util.Log
import androidx.annotation.VisibleForTesting
import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider
import com.android.settingslib.spa.framework.BrowseActivity import com.android.settingslib.spa.framework.BrowseActivity
import com.android.settingslib.spa.framework.common.SettingsPage
import com.android.settingslib.spa.framework.util.SESSION_BROWSE import com.android.settingslib.spa.framework.util.SESSION_BROWSE
import com.android.settingslib.spa.framework.util.SESSION_EXTERNAL import com.android.settingslib.spa.framework.util.SESSION_EXTERNAL
import com.android.settingslib.spa.framework.util.appendSpaParams import com.android.settingslib.spa.framework.util.appendSpaParams
import com.google.android.setupcompat.util.WizardManagerHelper
class SpaActivity : BrowseActivity() { class SpaActivity : BrowseActivity() {
override fun isPageEnabled(page: SettingsPage) =
super.isPageEnabled(page) && !isSuwAndPageBlocked(page.sppName)
companion object { companion object {
private const val TAG = "SpaActivity" private const val TAG = "SpaActivity"
/** The pages that blocked from SUW. */
private val SuwBlockedPages = setOf(AppInfoSettingsProvider.name)
@VisibleForTesting
fun Context.isSuwAndPageBlocked(name: String): Boolean =
if (name in SuwBlockedPages && !WizardManagerHelper.isDeviceProvisioned(this)) {
Log.w(TAG, "$name blocked before SUW completed.");
true
} else {
false
}
@JvmStatic @JvmStatic
fun Context.startSpaActivity(destination: String) { fun Context.startSpaActivity(destination: String) {
val intent = Intent(this, SpaActivity::class.java) val intent = Intent(this, SpaActivity::class.java)

View File

@@ -19,12 +19,14 @@ package com.android.settings.spa.app.specialaccess
import android.Manifest import android.Manifest
import android.app.AlarmManager import android.app.AlarmManager
import android.app.compat.CompatChanges import android.app.compat.CompatChanges
import android.app.settings.SettingsEnums
import android.content.Context import android.content.Context
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import android.os.PowerExemptionManager import android.os.PowerExemptionManager
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import com.android.settings.R import com.android.settings.R
import com.android.settings.overlay.FeatureFactory
import com.android.settingslib.spa.framework.compose.stateOf import com.android.settingslib.spa.framework.compose.stateOf
import com.android.settingslib.spaprivileged.model.app.AppRecord import com.android.settingslib.spaprivileged.model.app.AppRecord
import com.android.settingslib.spaprivileged.model.app.IPackageManagers import com.android.settingslib.spaprivileged.model.app.IPackageManagers
@@ -85,6 +87,17 @@ class AlarmsAndRemindersAppListModel(
override fun setAllowed(record: AlarmsAndRemindersAppRecord, newAllowed: Boolean) { override fun setAllowed(record: AlarmsAndRemindersAppRecord, newAllowed: Boolean) {
record.controller.setAllowed(newAllowed) record.controller.setAllowed(newAllowed)
logPermissionChange(newAllowed)
}
private fun logPermissionChange(newAllowed: Boolean) {
FeatureFactory.getFactory(context).metricsFeatureProvider.action(
SettingsEnums.PAGE_UNKNOWN,
SettingsEnums.ACTION_ALARMS_AND_REMINDERS_TOGGLE,
SettingsEnums.ALARMS_AND_REMINDERS,
"",
if (newAllowed) 1 else 0
)
} }
private fun createRecord( private fun createRecord(

View File

@@ -18,9 +18,12 @@ package com.android.settings.spa.app.specialaccess
import android.Manifest import android.Manifest
import android.app.AppOpsManager import android.app.AppOpsManager
import android.app.settings.SettingsEnums
import android.content.Context import android.content.Context
import com.android.settings.R import com.android.settings.R
import com.android.settings.overlay.FeatureFactory
import com.android.settingslib.spaprivileged.template.app.AppOpPermissionListModel import com.android.settingslib.spaprivileged.template.app.AppOpPermissionListModel
import com.android.settingslib.spaprivileged.template.app.AppOpPermissionRecord
import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider
object AllFilesAccessAppListProvider : TogglePermissionAppListProvider { object AllFilesAccessAppListProvider : TogglePermissionAppListProvider {
@@ -35,4 +38,17 @@ class AllFilesAccessListModel(context: Context) : AppOpPermissionListModel(conte
override val appOp = AppOpsManager.OP_MANAGE_EXTERNAL_STORAGE override val appOp = AppOpsManager.OP_MANAGE_EXTERNAL_STORAGE
override val permission = Manifest.permission.MANAGE_EXTERNAL_STORAGE override val permission = Manifest.permission.MANAGE_EXTERNAL_STORAGE
override val setModeByUid = true override val setModeByUid = true
override fun setAllowed(record: AppOpPermissionRecord, newAllowed: Boolean) {
super.setAllowed(record, newAllowed)
logPermissionChange(newAllowed)
}
private fun logPermissionChange(newAllowed: Boolean) {
val category = when {
newAllowed -> SettingsEnums.APP_SPECIAL_PERMISSION_MANAGE_EXT_STRG_ALLOW
else -> SettingsEnums.APP_SPECIAL_PERMISSION_MANAGE_EXT_STRG_DENY
}
FeatureFactory.getFactory(context).metricsFeatureProvider.action(context, category, "")
}
} }

View File

@@ -18,9 +18,12 @@ package com.android.settings.spa.app.specialaccess
import android.Manifest import android.Manifest
import android.app.AppOpsManager import android.app.AppOpsManager
import android.app.settings.SettingsEnums
import android.content.Context import android.content.Context
import com.android.settings.R import com.android.settings.R
import com.android.settings.overlay.FeatureFactory
import com.android.settingslib.spaprivileged.template.app.AppOpPermissionListModel import com.android.settingslib.spaprivileged.template.app.AppOpPermissionListModel
import com.android.settingslib.spaprivileged.template.app.AppOpPermissionRecord
import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider
object DisplayOverOtherAppsAppListProvider : TogglePermissionAppListProvider { object DisplayOverOtherAppsAppListProvider : TogglePermissionAppListProvider {
@@ -34,4 +37,17 @@ class DisplayOverOtherAppsListModel(context: Context) : AppOpPermissionListModel
override val footerResId = R.string.allow_overlay_description override val footerResId = R.string.allow_overlay_description
override val appOp = AppOpsManager.OP_SYSTEM_ALERT_WINDOW override val appOp = AppOpsManager.OP_SYSTEM_ALERT_WINDOW
override val permission = Manifest.permission.SYSTEM_ALERT_WINDOW override val permission = Manifest.permission.SYSTEM_ALERT_WINDOW
override fun setAllowed(record: AppOpPermissionRecord, newAllowed: Boolean) {
super.setAllowed(record, newAllowed)
logPermissionChange(newAllowed)
}
private fun logPermissionChange(newAllowed: Boolean) {
val category = when {
newAllowed -> SettingsEnums.APP_SPECIAL_PERMISSION_APPDRAW_ALLOW
else -> SettingsEnums.APP_SPECIAL_PERMISSION_APPDRAW_DENY
}
FeatureFactory.getFactory(context).metricsFeatureProvider.action(context, category, "")
}
} }

View File

@@ -18,9 +18,12 @@ package com.android.settings.spa.app.specialaccess
import android.Manifest import android.Manifest
import android.app.AppOpsManager import android.app.AppOpsManager
import android.app.settings.SettingsEnums
import android.content.Context import android.content.Context
import com.android.settings.R import com.android.settings.R
import com.android.settings.overlay.FeatureFactory
import com.android.settingslib.spaprivileged.template.app.AppOpPermissionListModel import com.android.settingslib.spaprivileged.template.app.AppOpPermissionListModel
import com.android.settingslib.spaprivileged.template.app.AppOpPermissionRecord
import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider
object MediaManagementAppsAppListProvider : TogglePermissionAppListProvider { object MediaManagementAppsAppListProvider : TogglePermissionAppListProvider {
@@ -35,4 +38,19 @@ class MediaManagementAppsListModel(context: Context) : AppOpPermissionListModel(
override val appOp = AppOpsManager.OP_MANAGE_MEDIA override val appOp = AppOpsManager.OP_MANAGE_MEDIA
override val permission = Manifest.permission.MANAGE_MEDIA override val permission = Manifest.permission.MANAGE_MEDIA
override val setModeByUid = true override val setModeByUid = true
override fun setAllowed(record: AppOpPermissionRecord, newAllowed: Boolean) {
super.setAllowed(record, newAllowed)
logPermissionChange(newAllowed)
}
private fun logPermissionChange(newAllowed: Boolean) {
FeatureFactory.getFactory(context).metricsFeatureProvider.action(
SettingsEnums.PAGE_UNKNOWN,
SettingsEnums.ACTION_MEDIA_MANAGEMENT_APPS_TOGGLE,
SettingsEnums.MEDIA_MANAGEMENT_APPS,
"",
if (newAllowed) 1 else 0
)
}
} }

View File

@@ -18,9 +18,12 @@ package com.android.settings.spa.app.specialaccess
import android.Manifest import android.Manifest
import android.app.AppOpsManager import android.app.AppOpsManager
import android.app.settings.SettingsEnums
import android.content.Context import android.content.Context
import com.android.settings.R import com.android.settings.R
import com.android.settings.overlay.FeatureFactory
import com.android.settingslib.spaprivileged.template.app.AppOpPermissionListModel import com.android.settingslib.spaprivileged.template.app.AppOpPermissionListModel
import com.android.settingslib.spaprivileged.template.app.AppOpPermissionRecord
import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider
object ModifySystemSettingsAppListProvider : TogglePermissionAppListProvider { object ModifySystemSettingsAppListProvider : TogglePermissionAppListProvider {
@@ -34,4 +37,17 @@ class ModifySystemSettingsListModel(context: Context) : AppOpPermissionListModel
override val footerResId = R.string.write_settings_description override val footerResId = R.string.write_settings_description
override val appOp = AppOpsManager.OP_WRITE_SETTINGS override val appOp = AppOpsManager.OP_WRITE_SETTINGS
override val permission = Manifest.permission.WRITE_SETTINGS override val permission = Manifest.permission.WRITE_SETTINGS
override fun setAllowed(record: AppOpPermissionRecord, newAllowed: Boolean) {
super.setAllowed(record, newAllowed)
logPermissionChange(newAllowed)
}
private fun logPermissionChange(newAllowed: Boolean) {
val category = when {
newAllowed -> SettingsEnums.APP_SPECIAL_PERMISSION_SETTINGS_CHANGE_ALLOW
else -> SettingsEnums.APP_SPECIAL_PERMISSION_SETTINGS_CHANGE_DENY
}
FeatureFactory.getFactory(context).metricsFeatureProvider.action(context, category, "")
}
} }

View File

@@ -0,0 +1,102 @@
/*
* Copyright (C) 2023 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.bluetooth
import android.bluetooth.BluetoothAdapter
import android.content.Intent
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.android.controller.ActivityController
import org.robolectric.annotation.Config
import org.robolectric.shadow.api.Shadow
import org.robolectric.shadows.ShadowBluetoothAdapter
@RunWith(RobolectricTestRunner::class)
@Config(shadows = [ShadowAlertDialogCompat::class, ShadowBluetoothAdapter::class])
class RequestPermissionActivityTest {
private lateinit var activityController: ActivityController<RequestPermissionActivity>
private lateinit var bluetoothAdapter: ShadowBluetoothAdapter
@Before
fun setUp() {
bluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter())
}
@After
fun tearDown() {
activityController.pause().stop().destroy()
ShadowAlertDialogCompat.reset()
}
@Test
fun requestEnable_whenBluetoothIsOff_showConfirmDialog() {
bluetoothAdapter.setState(BluetoothAdapter.STATE_OFF)
createActivity(action = BluetoothAdapter.ACTION_REQUEST_ENABLE)
val dialog = ShadowAlertDialogCompat.getLatestAlertDialog()
val shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog)
assertThat(shadowDialog.message.toString())
.isEqualTo("An app wants to turn on Bluetooth")
}
@Test
fun requestEnable_whenBluetoothIsOn_doNothing() {
bluetoothAdapter.setState(BluetoothAdapter.STATE_ON)
createActivity(action = BluetoothAdapter.ACTION_REQUEST_ENABLE)
val dialog = ShadowAlertDialogCompat.getLatestAlertDialog()
assertThat(dialog).isNull()
}
@Test
fun requestDisable_whenBluetoothIsOff_doNothing() {
bluetoothAdapter.setState(BluetoothAdapter.STATE_OFF)
createActivity(action = BluetoothAdapter.ACTION_REQUEST_DISABLE)
val dialog = ShadowAlertDialogCompat.getLatestAlertDialog()
assertThat(dialog).isNull()
}
@Test
fun requestDisable_whenBluetoothIsOn_showConfirmDialog() {
bluetoothAdapter.setState(BluetoothAdapter.STATE_ON)
createActivity(action = BluetoothAdapter.ACTION_REQUEST_DISABLE)
val dialog = ShadowAlertDialogCompat.getLatestAlertDialog()
val shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog)
assertThat(shadowDialog.message.toString())
.isEqualTo("An app wants to turn off Bluetooth")
}
private fun createActivity(action: String) {
activityController =
ActivityController.of(RequestPermissionActivity(), Intent(action)).apply {
create()
start()
postCreate(null)
resume()
}
}
}

View File

@@ -49,13 +49,14 @@ class RequestPermissionHelperTest {
@Test @Test
fun requestEnable_withAppLabelAndNoTimeout_hasCorrectMessage() { fun requestEnable_withAppLabelAndNoTimeout_hasCorrectMessage() {
val activity = activityController.get() val activity = activityController.get()
RequestPermissionHelper.requestEnable( RequestPermissionHelper.requestEnable(
context = activity, context = activity,
appLabel = "App Label", appLabel = "App Label",
timeout = -1, timeout = -1,
onAllow = {}, onAllow = {},
onDeny = {}, onDeny = {},
) )!!.show()
assertLatestMessageIs("App Label wants to turn on Bluetooth") assertLatestMessageIs("App Label wants to turn on Bluetooth")
} }
@@ -63,13 +64,14 @@ class RequestPermissionHelperTest {
@Test @Test
fun requestEnable_withAppLabelAndZeroTimeout_hasCorrectMessage() { fun requestEnable_withAppLabelAndZeroTimeout_hasCorrectMessage() {
val activity = activityController.get() val activity = activityController.get()
RequestPermissionHelper.requestEnable( RequestPermissionHelper.requestEnable(
context = activity, context = activity,
appLabel = "App Label", appLabel = "App Label",
timeout = 0, timeout = 0,
onAllow = {}, onAllow = {},
onDeny = {}, onDeny = {},
) )!!.show()
assertLatestMessageIs( assertLatestMessageIs(
"App Label wants to turn on Bluetooth and make your phone visible to other devices. " + "App Label wants to turn on Bluetooth and make your phone visible to other devices. " +
@@ -80,13 +82,14 @@ class RequestPermissionHelperTest {
@Test @Test
fun requestEnable_withAppLabelAndNormalTimeout_hasCorrectMessage() { fun requestEnable_withAppLabelAndNormalTimeout_hasCorrectMessage() {
val activity = activityController.get() val activity = activityController.get()
RequestPermissionHelper.requestEnable( RequestPermissionHelper.requestEnable(
context = activity, context = activity,
appLabel = "App Label", appLabel = "App Label",
timeout = 120, timeout = 120,
onAllow = {}, onAllow = {},
onDeny = {}, onDeny = {},
) )!!.show()
assertLatestMessageIs( assertLatestMessageIs(
"App Label wants to turn on Bluetooth and make your phone visible to other devices " + "App Label wants to turn on Bluetooth and make your phone visible to other devices " +
@@ -97,13 +100,14 @@ class RequestPermissionHelperTest {
@Test @Test
fun requestEnable_withNoAppLabelAndNoTimeout_hasCorrectMessage() { fun requestEnable_withNoAppLabelAndNoTimeout_hasCorrectMessage() {
val activity = activityController.get() val activity = activityController.get()
RequestPermissionHelper.requestEnable( RequestPermissionHelper.requestEnable(
context = activity, context = activity,
appLabel = null, appLabel = null,
timeout = -1, timeout = -1,
onAllow = {}, onAllow = {},
onDeny = {}, onDeny = {},
) )!!.show()
assertLatestMessageIs("An app wants to turn on Bluetooth") assertLatestMessageIs("An app wants to turn on Bluetooth")
} }
@@ -111,13 +115,14 @@ class RequestPermissionHelperTest {
@Test @Test
fun requestEnable_withNoAppLabelAndZeroTimeout_hasCorrectMessage() { fun requestEnable_withNoAppLabelAndZeroTimeout_hasCorrectMessage() {
val activity = activityController.get() val activity = activityController.get()
RequestPermissionHelper.requestEnable( RequestPermissionHelper.requestEnable(
context = activity, context = activity,
appLabel = null, appLabel = null,
timeout = 0, timeout = 0,
onAllow = {}, onAllow = {},
onDeny = {}, onDeny = {},
) )!!.show()
assertLatestMessageIs( assertLatestMessageIs(
"An app wants to turn on Bluetooth and make your phone visible to other devices. " + "An app wants to turn on Bluetooth and make your phone visible to other devices. " +
@@ -128,13 +133,14 @@ class RequestPermissionHelperTest {
@Test @Test
fun requestEnable_withNoAppLabelAndNormalTimeout_hasCorrectMessage() { fun requestEnable_withNoAppLabelAndNormalTimeout_hasCorrectMessage() {
val activity = activityController.get() val activity = activityController.get()
RequestPermissionHelper.requestEnable( RequestPermissionHelper.requestEnable(
context = activity, context = activity,
appLabel = null, appLabel = null,
timeout = 120, timeout = 120,
onAllow = {}, onAllow = {},
onDeny = {}, onDeny = {},
) )!!.show()
assertLatestMessageIs( assertLatestMessageIs(
"An app wants to turn on Bluetooth and make your phone visible to other devices for " + "An app wants to turn on Bluetooth and make your phone visible to other devices for " +
@@ -177,12 +183,13 @@ class RequestPermissionHelperTest {
@Test @Test
fun requestDisable_withAppLabel_hasCorrectMessage() { fun requestDisable_withAppLabel_hasCorrectMessage() {
val activity = activityController.get() val activity = activityController.get()
RequestPermissionHelper.requestDisable( RequestPermissionHelper.requestDisable(
context = activity, context = activity,
appLabel = "App Label", appLabel = "App Label",
onAllow = {}, onAllow = {},
onDeny = {}, onDeny = {},
) )!!.show()
assertLatestMessageIs("App Label wants to turn off Bluetooth") assertLatestMessageIs("App Label wants to turn off Bluetooth")
} }
@@ -190,12 +197,13 @@ class RequestPermissionHelperTest {
@Test @Test
fun requestDisable_withNoAppLabel_hasCorrectMessage() { fun requestDisable_withNoAppLabel_hasCorrectMessage() {
val activity = activityController.get() val activity = activityController.get()
RequestPermissionHelper.requestDisable( RequestPermissionHelper.requestDisable(
context = activity, context = activity,
appLabel = null, appLabel = null,
onAllow = {}, onAllow = {},
onDeny = {}, onDeny = {},
) )!!.show()
assertLatestMessageIs("An app wants to turn off Bluetooth") assertLatestMessageIs("An app wants to turn off Bluetooth")
} }

View File

@@ -61,22 +61,9 @@ public class TrackpadReverseScrollingPreferenceControllerTest {
} }
@Test @Test
public void setChecked_true_shouldReturn1() { public void setChecked_true_shouldReturn0() {
mController.setChecked(true); mController.setChecked(true);
int result = Settings.System.getIntForUser(
mContext.getContentResolver(),
SETTING_KEY,
0,
UserHandle.USER_CURRENT);
assertThat(result).isEqualTo(1);
}
@Test
public void setChecked_false_shouldReturn0() {
mController.setChecked(false);
int result = Settings.System.getIntForUser( int result = Settings.System.getIntForUser(
mContext.getContentResolver(), mContext.getContentResolver(),
SETTING_KEY, SETTING_KEY,
@@ -87,7 +74,20 @@ public class TrackpadReverseScrollingPreferenceControllerTest {
} }
@Test @Test
public void isChecked_providerPutInt1_returnTrue() { public void setChecked_false_shouldReturn1() {
mController.setChecked(false);
int result = Settings.System.getIntForUser(
mContext.getContentResolver(),
SETTING_KEY,
0,
UserHandle.USER_CURRENT);
assertThat(result).isEqualTo(1);
}
@Test
public void isChecked_providerPutInt1_returnFalse() {
Settings.System.putIntForUser( Settings.System.putIntForUser(
mContext.getContentResolver(), mContext.getContentResolver(),
SETTING_KEY, SETTING_KEY,
@@ -96,11 +96,11 @@ public class TrackpadReverseScrollingPreferenceControllerTest {
boolean result = mController.isChecked(); boolean result = mController.isChecked();
assertThat(result).isTrue(); assertThat(result).isFalse();
} }
@Test @Test
public void isChecked_providerPutInt0_returnFalse() { public void isChecked_providerPutInt0_returnTrue() {
Settings.System.putIntForUser( Settings.System.putIntForUser(
mContext.getContentResolver(), mContext.getContentResolver(),
SETTING_KEY, SETTING_KEY,
@@ -109,6 +109,6 @@ public class TrackpadReverseScrollingPreferenceControllerTest {
boolean result = mController.isChecked(); boolean result = mController.isChecked();
assertThat(result).isFalse(); assertThat(result).isTrue();
} }
} }

View File

@@ -21,33 +21,71 @@ import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.UserHandle import android.os.UserHandle
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.dx.mockito.inline.extended.ExtendedMockito
import com.android.settings.spa.SpaActivity.Companion.isSuwAndPageBlocked
import com.android.settings.spa.SpaActivity.Companion.startSpaActivity import com.android.settings.spa.SpaActivity.Companion.startSpaActivity
import com.android.settings.spa.SpaActivity.Companion.startSpaActivityForApp import com.android.settings.spa.SpaActivity.Companion.startSpaActivityForApp
import com.android.settings.spa.app.AllAppListPageProvider
import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider
import com.android.settingslib.spa.framework.util.KEY_DESTINATION import com.android.settingslib.spa.framework.util.KEY_DESTINATION
import com.google.android.setupcompat.util.WizardManagerHelper
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.Answers
import org.mockito.ArgumentCaptor import org.mockito.ArgumentCaptor
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.verify import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` import org.mockito.MockitoSession
import org.mockito.junit.MockitoJUnit import org.mockito.quality.Strictness
import org.mockito.junit.MockitoRule import org.mockito.Mockito.`when` as whenever
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
class SpaActivityTest { class SpaActivityTest {
@get:Rule private lateinit var mockSession: MockitoSession
val mockito: MockitoRule = MockitoJUnit.rule()
@Mock(answer = Answers.RETURNS_DEEP_STUBS) @Mock
private lateinit var context: Context private lateinit var context: Context
@Before @Before
fun setUp() { fun setUp() {
`when`(context.applicationContext.packageName).thenReturn("com.android.settings") mockSession = ExtendedMockito.mockitoSession()
.initMocks(this)
.mockStatic(WizardManagerHelper::class.java)
.strictness(Strictness.LENIENT)
.startMocking()
whenever(context.applicationContext).thenReturn(context)
}
@After
fun tearDown() {
mockSession.finishMocking()
}
@Test
fun isSuwAndPageBlocked_regularPage_notBlocked() {
val isBlocked = context.isSuwAndPageBlocked(AllAppListPageProvider.name)
assertThat(isBlocked).isFalse()
}
@Test
fun isSuwAndPageBlocked_blocklistedPageInSuw_blocked() {
whenever(WizardManagerHelper.isDeviceProvisioned(context)).thenReturn(false)
val isBlocked = context.isSuwAndPageBlocked(AppInfoSettingsProvider.name)
assertThat(isBlocked).isTrue()
}
@Test
fun isSuwAndPageBlocked_blocklistedPageNotInSuw_notBlocked() {
whenever(WizardManagerHelper.isDeviceProvisioned(context)).thenReturn(true)
val isBlocked = context.isSuwAndPageBlocked(AppInfoSettingsProvider.name)
assertThat(isBlocked).isFalse()
} }
@Test @Test