Merge changes from topic "integrate-auto-rotate-manager" into main
* changes:
Refactor ShadowDeviceStateAutoRotateSettingManager
Integrate refactored device-state auto-rotate setting manager
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ac99f2d..6d865c2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -14360,6 +14360,16 @@
<string name="supervision_web_content_filters_browser_block_explicit_sites_summary">No filter is perfect, but this should help hide sexually explicit sites</string>
<!-- Title for web content filters browser category allow all sites option [CHAR LIMIT=60] -->
<string name="supervision_web_content_filters_browser_allow_all_sites_title">Allow all sites</string>
+ <!-- Title for web content filters search category [CHAR LIMIT=60] -->
+ <string name="supervision_web_content_filters_search_title">Google Search</string>
+ <!-- Title for web content filters search category filter on option [CHAR LIMIT=60] -->
+ <string name="supervision_web_content_filters_search_filter_on_title">SafeSearch filtering ON</string>
+ <!-- Summary for web content filters search category filter on option [CHAR LIMIT=None] -->
+ <string name="supervision_web_content_filters_search_filter_on_summary">Helps filter out explicit images, text, and links from search results on this device</string>
+ <!-- Title for web content filters search category filter off option [CHAR LIMIT=60] -->
+ <string name="supervision_web_content_filters_search_filter_off_title">SafeSearch filtering OFF</string>
+ <!-- Summary for web content filters search category filter off option [CHAR LIMIT=None] -->
+ <string name="supervision_web_content_filters_search_filter_off_summary">Account settings may still filter or blur explicit results</string>
<!-- Generic content description that is attached to the preview illustration at the top of an Accessibility feature toggle page. [CHAR LIMIT=NONE] -->
<!-- Title for supervision PIN verification screen [CHAR LIMIT=60] -->
<string name="supervision_full_screen_pin_verification_title">Enter supervision PIN</string>
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
index 92ebc57..f1fcd69 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
@@ -192,7 +192,7 @@
Log.d(TAG, "Skip handleOnBroadcastReady, not in starting process");
return;
}
- handleOnBroadcastReady();
+ handleOnBroadcastReady(metadata);
}
@Override
@@ -273,7 +273,7 @@
+ mSinksInAdding);
if (mSinksToWaitFor.contains(sink)) {
mSinksToWaitFor.remove(sink);
- if (mSinksToWaitFor.isEmpty()) {
+ if (mSinksToWaitFor.isEmpty() && mBroadcast != null) {
// To avoid users advance to share then pair flow before the
// primary/active sinks successfully join the audio sharing,
// popup dialog till adding source complete for mSinksToWaitFor.
@@ -284,7 +284,8 @@
/* userTriggered= */ false,
/* deviceCountInSharing= */ 1,
/* candidateDeviceCount= */ 0);
- showAudioSharingDialog(eventData);
+ showJoinAudioSharingDialog(eventData,
+ mBroadcast.getLatestBluetoothLeBroadcastMetadata());
}
}
}
@@ -501,9 +502,10 @@
mBtManager == null ? null : mBtManager.getCachedDeviceManager();
CachedBluetoothDevice cachedDevice =
deviceManager == null ? null : deviceManager.findDevice(device);
- if (cachedDevice != null) {
+ if (cachedDevice != null && mBroadcast != null) {
Log.d(TAG, "handleAutoAddSourceAfterPair, device = " + device.getAnonymizedAddress());
- addSourceToTargetSinks(ImmutableList.of(device), cachedDevice.getName());
+ addSourceToTargetSinks(ImmutableList.of(device), cachedDevice.getName(),
+ mBroadcast.getLatestBluetoothLeBroadcastMetadata());
}
}
@@ -642,7 +644,7 @@
return mAssistant != null && mAssistant.getAllConnectedDevices().isEmpty();
}
- private void handleOnBroadcastReady() {
+ private void handleOnBroadcastReady(@NonNull BluetoothLeBroadcastMetadata metadata) {
List<BluetoothDevice> targetActiveSinks = mTargetActiveItem == null ? ImmutableList.of()
: mGroupedConnectedDevices.getOrDefault(
mTargetActiveItem.getGroupId(), ImmutableList.of());
@@ -656,7 +658,7 @@
// Auto add primary/active sinks w/o user interactions.
if (!targetActiveSinks.isEmpty() && mTargetActiveItem != null) {
Log.d(TAG, "handleOnBroadcastReady: automatically add source to active sinks.");
- addSourceToTargetSinks(targetActiveSinks, mTargetActiveItem.getName());
+ addSourceToTargetSinks(targetActiveSinks, mTargetActiveItem.getName(), metadata);
// To avoid users advance to share then pair flow before the primary/active sinks
// successfully join the audio sharing, save the primary/active sinks in mSinksToWaitFor
// and popup dialog till adding source complete for these sinks.
@@ -677,7 +679,7 @@
AudioSharingDeviceItem target = mDeviceItemsForSharing.get(0);
List<BluetoothDevice> targetSinks = mGroupedConnectedDevices.getOrDefault(
target.getGroupId(), ImmutableList.of());
- addSourceToTargetSinks(targetSinks, target.getName());
+ addSourceToTargetSinks(targetSinks, target.getName(), metadata);
cleanUpStatesForStartSharing();
// TODO: Add metric for auto add by intent
return;
@@ -698,20 +700,21 @@
// successfully join the audio sharing, popup dialog till adding source complete for
// mSinksToWaitFor.
if (mSinksToWaitFor.isEmpty() && !mStoppingSharing.get()) {
- showAudioSharingDialog(eventData);
+ showJoinAudioSharingDialog(eventData, metadata);
}
}
- private void showAudioSharingDialog(Pair<Integer, Object>[] eventData) {
+ private void showJoinAudioSharingDialog(Pair<Integer, Object>[] eventData,
+ @Nullable BluetoothLeBroadcastMetadata metadata) {
if (!BluetoothUtils.isBroadcasting(mBtManager)) {
- Log.d(TAG, "Skip showAudioSharingDialog, broadcast is stopped");
+ Log.d(TAG, "Skip showJoinAudioSharingDialog, broadcast is stopped");
return;
}
AudioSharingDialogFragment.DialogEventListener listener =
new AudioSharingDialogFragment.DialogEventListener() {
@Override
public void onPositiveClick() {
- // Could go to other pages, dismiss the progress dialog.
+ // Could go to other pages (pair new device), dismiss the progress dialog.
dismissProgressDialogIfNeeded();
cleanUpStatesForStartSharing();
}
@@ -720,19 +723,17 @@
public void onItemClick(@NonNull AudioSharingDeviceItem item) {
List<BluetoothDevice> targetSinks = mGroupedConnectedDevices.getOrDefault(
item.getGroupId(), ImmutableList.of());
- addSourceToTargetSinks(targetSinks, item.getName());
+ addSourceToTargetSinks(targetSinks, item.getName(), metadata);
cleanUpStatesForStartSharing();
}
@Override
public void onCancelClick() {
- // Could go to other pages, dismiss the progress dialog.
+ // Could go to other pages (show qr code), dismiss the progress dialog.
dismissProgressDialogIfNeeded();
cleanUpStatesForStartSharing();
}
};
- BluetoothLeBroadcastMetadata metadata = mBroadcast == null ? null
- : mBroadcast.getLatestBluetoothLeBroadcastMetadata();
AudioSharingUtils.postOnMainThread(
mContext,
() -> AudioSharingDialogFragment.show(
@@ -828,13 +829,27 @@
});
}
- private void addSourceToTargetSinks(List<BluetoothDevice> targetActiveSinks,
- @NonNull String sinkName) {
- mSinksInAdding.addAll(targetActiveSinks);
+ private void addSourceToTargetSinks(List<BluetoothDevice> targetGroupedSinks,
+ @NonNull String targetSinkName, @Nullable BluetoothLeBroadcastMetadata metadata) {
+ if (targetGroupedSinks.isEmpty()) {
+ Log.d(TAG, "Skip addSourceToTargetSinks, no sinks.");
+ return;
+ }
+ if (metadata == null) {
+ Log.d(TAG, "Skip addSourceToTargetSinks, metadata is null");
+ return;
+ }
+ if (mAssistant == null) {
+ Log.d(TAG, "skip addSourceToTargetDevices, assistant profile is null.");
+ return;
+ }
+ mSinksInAdding.addAll(targetGroupedSinks);
String progressMessage = mContext.getString(
- R.string.audio_sharing_progress_dialog_add_source_content, sinkName);
+ R.string.audio_sharing_progress_dialog_add_source_content, targetSinkName);
showProgressDialog(progressMessage);
- AudioSharingUtils.addSourceToTargetSinks(targetActiveSinks, mBtManager);
+ for (BluetoothDevice sink : targetGroupedSinks) {
+ mAssistant.addSource(sink, metadata, /* isGroupOp= */ false);
+ }
}
private void showProgressDialog(@NonNull String progressMessage) {
diff --git a/src/com/android/settings/contract/SettingsContract.kt b/src/com/android/settings/contract/SettingsContract.kt
index 3a35419..20ff0c0 100644
--- a/src/com/android/settings/contract/SettingsContract.kt
+++ b/src/com/android/settings/contract/SettingsContract.kt
@@ -69,6 +69,12 @@
/** Contract key for the "Use adaptive connectivity" setting. */
const val KEY_ADAPTIVE_CONNECTIVITY = "adaptive_connectivity"
+/** Contract key for the "Auto-switch Wi-Fi to Cellular" setting. */
+const val KEY_ADAPTIVE_WIFI_SCORER = "adaptive_wifi_scorer"
+
+/** Contract key for the " Auto-switch mobile network for battery life" setting. */
+const val KEY_ADAPTIVE_MOBILE_NETWORK = "adaptive_mobile_network"
+
/** Contract key for the "WiFi hotspot" setting. */
const val KEY_WIFI_HOTSPOT = "enable_wifi_ap"
diff --git a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
index b49d62d..bb39d88 100644
--- a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
@@ -65,9 +65,10 @@
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
- if (!SubscriptionUtil.isSimHardwareVisible(mContext)) {
+ if (!isAvailable()) {
return;
}
+
final Preference preference = screen.findPreference(getPreferenceKey());
final PreferenceCategory category = screen.findPreference(KEY_PREFERENCE_CATEGORY);
mPreferenceList.add(preference);
diff --git a/src/com/android/settings/network/telephony/satellite/SatelliteSettingsPreferenceCategoryController.java b/src/com/android/settings/network/telephony/satellite/SatelliteSettingsPreferenceCategoryController.java
index f2fb347..d0cb1bc 100644
--- a/src/com/android/settings/network/telephony/satellite/SatelliteSettingsPreferenceCategoryController.java
+++ b/src/com/android/settings/network/telephony/satellite/SatelliteSettingsPreferenceCategoryController.java
@@ -159,6 +159,7 @@
@Override
public void onResult(Boolean result) {
mIsSatelliteSupported.set(result);
+ Log.d(TAG, "Satellite requestIsSupported : " + result);
SatelliteSettingsPreferenceCategoryController.this.displayPreference();
}
});
diff --git a/src/com/android/settings/safetycenter/BiometricSourcesUtils.java b/src/com/android/settings/safetycenter/BiometricSourcesUtils.java
index 786e3cf..9cadbbb 100644
--- a/src/com/android/settings/safetycenter/BiometricSourcesUtils.java
+++ b/src/com/android/settings/safetycenter/BiometricSourcesUtils.java
@@ -19,15 +19,11 @@
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
-import android.hardware.face.FaceManager;
-import android.hardware.fingerprint.FingerprintManager;
import android.safetycenter.SafetyEvent;
import android.safetycenter.SafetySourceData;
import android.safetycenter.SafetySourceIssue;
import android.safetycenter.SafetySourceStatus;
-import com.android.settings.Utils;
-
/** Static helpers for setting SafetyCenter data for biometric safety sources. */
public final class BiometricSourcesUtils {
@@ -93,15 +89,6 @@
.setSafetySourceData(context, safetySourceId, safetySourceData, safetyEvent);
}
- /** Check whether the multiple biometrics enrollment is needed. */
- public static boolean isMultipleBiometricsEnrollmentNeeded(Context context, int userId) {
- FaceManager faceManager = Utils.getFaceManagerOrNull(context);
- FingerprintManager fingerprintManager = Utils.getFingerprintManagerOrNull(context);
- return Utils.isMultipleBiometricsSupported(context)
- && !faceManager.hasEnrolledTemplates(userId)
- && !fingerprintManager.hasEnrolledFingerprints(userId);
- }
-
/** Helper method for creating a pending intent. */
public static PendingIntent createPendingIntent(
Context context, Intent intent, int requestCode) {
diff --git a/src/com/android/settings/safetycenter/FaceSafetySource.java b/src/com/android/settings/safetycenter/FaceSafetySource.java
index c5bde6e..73b6df5 100644
--- a/src/com/android/settings/safetycenter/FaceSafetySource.java
+++ b/src/com/android/settings/safetycenter/FaceSafetySource.java
@@ -16,7 +16,6 @@
package com.android.settings.safetycenter;
-import static com.android.settings.biometrics.BiometricEnrollActivity.EXTRA_LAUNCH_FACE_ENROLL_FIRST;
import static com.android.settings.safetycenter.BiometricSourcesUtils.REQUEST_CODE_FACE_SETTING;
import android.content.Context;
@@ -28,7 +27,6 @@
import android.safetycenter.SafetyEvent;
import com.android.settings.Utils;
-import com.android.settings.biometrics.BiometricEnrollActivity;
import com.android.settings.biometrics.BiometricNavigationUtils;
import com.android.settings.biometrics.face.FaceStatusUtils;
import com.android.settings.flags.Flags;
@@ -75,16 +73,6 @@
Context profileParentContext = context.createContextAsUser(profileParentUserHandle, 0);
if (Utils.hasFaceHardware(context)) {
- boolean isMultipleBiometricsEnrollmentNeeded =
- BiometricSourcesUtils.isMultipleBiometricsEnrollmentNeeded(context, userId);
- String settingClassName = isMultipleBiometricsEnrollmentNeeded
- ? BiometricEnrollActivity.class.getName()
- : faceStatusUtils.getSettingsClassName();
- Bundle bundle = new Bundle();
- if (isMultipleBiometricsEnrollmentNeeded) {
- // Launch face enrollment first then fingerprint enrollment.
- bundle.putBoolean(EXTRA_LAUNCH_FACE_ENROLL_FIRST, true);
- }
RestrictedLockUtils.EnforcedAdmin disablingAdmin = faceStatusUtils.getDisablingAdmin();
BiometricSourcesUtils.setBiometricSafetySourceData(
SAFETY_SOURCE_ID,
@@ -96,9 +84,9 @@
biometricNavigationUtils
.getBiometricSettingsIntent(
context,
- settingClassName,
+ faceStatusUtils.getSettingsClassName(),
disablingAdmin,
- bundle)
+ Bundle.EMPTY)
.setIdentifier(Integer.toString(userId)),
REQUEST_CODE_FACE_SETTING),
disablingAdmin == null /* enabled */,
diff --git a/src/com/android/settings/safetycenter/FingerprintSafetySource.java b/src/com/android/settings/safetycenter/FingerprintSafetySource.java
index 752fa69..62f218b 100644
--- a/src/com/android/settings/safetycenter/FingerprintSafetySource.java
+++ b/src/com/android/settings/safetycenter/FingerprintSafetySource.java
@@ -27,7 +27,6 @@
import android.safetycenter.SafetyEvent;
import com.android.settings.Utils;
-import com.android.settings.biometrics.BiometricEnrollActivity;
import com.android.settings.biometrics.BiometricNavigationUtils;
import com.android.settings.biometrics.fingerprint.FingerprintStatusUtils;
import com.android.settings.flags.Flags;
@@ -75,11 +74,6 @@
Context profileParentContext = context.createContextAsUser(profileParentUserHandle, 0);
if (Utils.hasFingerprintHardware(context)) {
- boolean isMultipleBiometricsEnrollmentNeeded =
- BiometricSourcesUtils.isMultipleBiometricsEnrollmentNeeded(context, userId);
- String settingClassName = isMultipleBiometricsEnrollmentNeeded
- ? BiometricEnrollActivity.class.getName()
- : fingerprintStatusUtils.getSettingsClassName();
RestrictedLockUtils.EnforcedAdmin disablingAdmin =
fingerprintStatusUtils.getDisablingAdmin();
BiometricSourcesUtils.setBiometricSafetySourceData(
@@ -92,7 +86,7 @@
biometricNavigationUtils
.getBiometricSettingsIntent(
context,
- settingClassName,
+ fingerprintStatusUtils.getSettingsClassName(),
disablingAdmin,
Bundle.EMPTY)
.setIdentifier(Integer.toString(userId)),
diff --git a/src/com/android/settings/supervision/SupervisionSafeSearchPreference.kt b/src/com/android/settings/supervision/SupervisionSafeSearchPreference.kt
new file mode 100644
index 0000000..617a345
--- /dev/null
+++ b/src/com/android/settings/supervision/SupervisionSafeSearchPreference.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2025 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.supervision
+
+import android.content.Context
+import androidx.preference.Preference
+import com.android.settings.R
+import com.android.settingslib.datastore.KeyValueStore
+import com.android.settingslib.datastore.Permissions
+import com.android.settingslib.datastore.SettingsSecureStore
+import com.android.settingslib.metadata.BooleanValuePreference
+import com.android.settingslib.metadata.PreferenceMetadata
+import com.android.settingslib.metadata.ReadWritePermit
+import com.android.settingslib.metadata.SensitivityLevel
+import com.android.settingslib.preference.PreferenceBinding
+import com.android.settingslib.preference.forEachRecursively
+import com.android.settingslib.widget.SelectorWithWidgetPreference
+
+/** Base class of web content filters SafeSearch preferences. */
+sealed class SupervisionSafeSearchPreference :
+ BooleanValuePreference, SelectorWithWidgetPreference.OnClickListener, PreferenceBinding {
+ override fun storage(context: Context): KeyValueStore = SettingsSecureStore.get(context)
+
+ override fun getReadPermissions(context: Context) = Permissions.EMPTY
+
+ override fun getWritePermissions(context: Context) = Permissions.EMPTY
+
+ override fun getReadPermit(context: Context, callingPid: Int, callingUid: Int) =
+ ReadWritePermit.ALLOW
+
+ override fun getWritePermit(
+ context: Context,
+ value: Boolean?,
+ callingPid: Int,
+ callingUid: Int,
+ ) = ReadWritePermit.DISALLOW
+
+ override val sensitivityLevel
+ get() = SensitivityLevel.NO_SENSITIVITY
+
+ override fun createWidget(context: Context) = SelectorWithWidgetPreference(context)
+
+ override fun onRadioButtonClicked(emiter: SelectorWithWidgetPreference) {
+ emiter.parent?.forEachRecursively {
+ if (it is SelectorWithWidgetPreference) {
+ it.isChecked = it == emiter
+ }
+ }
+ }
+
+ override fun bind(preference: Preference, metadata: PreferenceMetadata) {
+ super.bind(preference, metadata)
+ (preference as SelectorWithWidgetPreference).also {
+ // TODO(b/401568995): Set the isChecked value using stored values.
+ it.isChecked = (it.key == SupervisionSearchFilterOffPreference.KEY)
+ it.setOnClickListener(this)
+ }
+ }
+}
+
+/** The SafeSearch filter on preference. */
+class SupervisionSearchFilterOnPreference : SupervisionSafeSearchPreference() {
+
+ override val key
+ get() = KEY
+
+ override val title
+ get() = R.string.supervision_web_content_filters_search_filter_on_title
+
+ override val summary
+ get() = R.string.supervision_web_content_filters_search_filter_on_summary
+
+ companion object {
+ const val KEY = "web_content_filters_search_filter_on"
+ }
+}
+
+/** The SafeSearch filter off preference. */
+class SupervisionSearchFilterOffPreference : SupervisionSafeSearchPreference() {
+
+ override val key
+ get() = KEY
+
+ override val title
+ get() = R.string.supervision_web_content_filters_search_filter_off_title
+
+ override val summary
+ get() = R.string.supervision_web_content_filters_search_filter_off_summary
+
+ companion object {
+ const val KEY = "web_content_filters_search_filter_off"
+ }
+}
diff --git a/src/com/android/settings/supervision/SupervisionSafeSitesDataStore.kt b/src/com/android/settings/supervision/SupervisionSafeSitesDataStore.kt
new file mode 100644
index 0000000..4f283b8
--- /dev/null
+++ b/src/com/android/settings/supervision/SupervisionSafeSitesDataStore.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2025 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.supervision
+
+import android.content.Context
+import android.provider.Settings.Secure.BROWSER_CONTENT_FILTERS_ENABLED
+import com.android.settingslib.datastore.AbstractKeyedDataObservable
+import com.android.settingslib.datastore.HandlerExecutor
+import com.android.settingslib.datastore.KeyValueStore
+import com.android.settingslib.datastore.KeyedObserver
+import com.android.settingslib.datastore.SettingsSecureStore
+import com.android.settingslib.datastore.SettingsStore
+
+/** Datastore of the safe sites preference. */
+@Suppress("UNCHECKED_CAST")
+class SupervisionSafeSitesDataStore(
+ private val context: Context,
+ private val settingsStore: SettingsStore = SettingsSecureStore.get(context),
+) : AbstractKeyedDataObservable<String>(), KeyedObserver<String>, KeyValueStore {
+
+ override fun contains(key: String) =
+ key == SupervisionBlockExplicitSitesPreference.KEY ||
+ key == SupervisionAllowAllSitesPreference.KEY
+
+ override fun <T : Any> getValue(key: String, valueType: Class<T>): T? {
+ val settingValue = (settingsStore.getBoolean(BROWSER_CONTENT_FILTERS_ENABLED) == true)
+ return when (key) {
+ SupervisionAllowAllSitesPreference.KEY -> !settingValue
+
+ SupervisionBlockExplicitSitesPreference.KEY -> settingValue
+
+ else -> null
+ }
+ as T?
+ }
+
+ override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
+ if (value !is Boolean) return
+ when (key) {
+ SupervisionAllowAllSitesPreference.KEY ->
+ settingsStore.setBoolean(BROWSER_CONTENT_FILTERS_ENABLED, !value)
+
+ SupervisionBlockExplicitSitesPreference.KEY ->
+ settingsStore.setBoolean(BROWSER_CONTENT_FILTERS_ENABLED, value)
+ }
+ }
+
+ override fun onFirstObserverAdded() {
+ // observe the underlying storage key
+ settingsStore.addObserver(BROWSER_CONTENT_FILTERS_ENABLED, this, HandlerExecutor.main)
+ }
+
+ override fun onKeyChanged(key: String, reason: Int) {
+ // forward data change to preference hierarchy key
+ notifyChange(SupervisionBlockExplicitSitesPreference.KEY, reason)
+ notifyChange(SupervisionAllowAllSitesPreference.KEY, reason)
+ }
+
+ override fun onLastObserverRemoved() {
+ settingsStore.removeObserver(BROWSER_CONTENT_FILTERS_ENABLED, this)
+ }
+}
diff --git a/src/com/android/settings/supervision/SupervisionSafeSitesPreference.kt b/src/com/android/settings/supervision/SupervisionSafeSitesPreference.kt
index aaa5a33..d78afb2 100644
--- a/src/com/android/settings/supervision/SupervisionSafeSitesPreference.kt
+++ b/src/com/android/settings/supervision/SupervisionSafeSitesPreference.kt
@@ -18,9 +18,7 @@
import android.content.Context
import androidx.preference.Preference
import com.android.settings.R
-import com.android.settingslib.datastore.KeyValueStore
import com.android.settingslib.datastore.Permissions
-import com.android.settingslib.datastore.SettingsSecureStore
import com.android.settingslib.metadata.BooleanValuePreference
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.metadata.ReadWritePermit
@@ -30,9 +28,10 @@
import com.android.settingslib.widget.SelectorWithWidgetPreference
/** Base class of web content filters Safe sites preferences. */
-sealed class SupervisionSafeSitesPreference :
- BooleanValuePreference, SelectorWithWidgetPreference.OnClickListener, PreferenceBinding {
- override fun storage(context: Context): KeyValueStore = SettingsSecureStore.get(context)
+sealed class SupervisionSafeSitesPreference(
+ protected val dataStore: SupervisionSafeSitesDataStore
+) : BooleanValuePreference, SelectorWithWidgetPreference.OnClickListener, PreferenceBinding {
+ override fun storage(context: Context) = dataStore
override fun getReadPermissions(context: Context) = Permissions.EMPTY
@@ -64,15 +63,15 @@
override fun bind(preference: Preference, metadata: PreferenceMetadata) {
super.bind(preference, metadata)
(preference as SelectorWithWidgetPreference).also {
- // TODO(b/401568468): Set the isChecked value using stored values.
- it.isChecked = (it.key == SupervisionAllowAllSitesPreference.KEY)
+ it.isChecked = (dataStore.getBoolean(it.key) == true)
it.setOnClickListener(this)
}
}
}
/** The "Try to block explicit sites" preference. */
-class SupervisionBlockExplicitSitesPreference : SupervisionSafeSitesPreference() {
+class SupervisionBlockExplicitSitesPreference(dataStore: SupervisionSafeSitesDataStore) :
+ SupervisionSafeSitesPreference(dataStore) {
override val key
get() = KEY
@@ -89,7 +88,8 @@
}
/** The "Allow all sites" preference. */
-class SupervisionAllowAllSitesPreference : SupervisionSafeSitesPreference() {
+class SupervisionAllowAllSitesPreference(dataStore: SupervisionSafeSitesDataStore) :
+ SupervisionSafeSitesPreference(dataStore) {
override val key
get() = KEY
diff --git a/src/com/android/settings/supervision/SupervisionWebContentFiltersScreen.kt b/src/com/android/settings/supervision/SupervisionWebContentFiltersScreen.kt
index 0a2891b..994165a 100644
--- a/src/com/android/settings/supervision/SupervisionWebContentFiltersScreen.kt
+++ b/src/com/android/settings/supervision/SupervisionWebContentFiltersScreen.kt
@@ -47,14 +47,23 @@
R.string.supervision_web_content_filters_browser_title,
) +=
{
- +SupervisionBlockExplicitSitesPreference()
- +SupervisionAllowAllSitesPreference()
+ val dataStore = SupervisionSafeSitesDataStore(context)
+ +SupervisionBlockExplicitSitesPreference(dataStore)
+ +SupervisionAllowAllSitesPreference(dataStore)
}
- // TODO(b/401569571) implement the SafeSearch group.
+ +PreferenceCategory(
+ SEARCH_RADIO_BUTTON_GROUP,
+ R.string.supervision_web_content_filters_search_title,
+ ) +=
+ {
+ +SupervisionSearchFilterOnPreference()
+ +SupervisionSearchFilterOffPreference()
+ }
}
companion object {
const val KEY = "supervision_web_content_filters"
internal const val BROWSER_RADIO_BUTTON_GROUP = "browser_radio_button_group"
+ internal const val SEARCH_RADIO_BUTTON_GROUP = "search_radio_button_group"
}
}
diff --git a/tests/robotests/src/com/android/settings/supervision/SupervisionSafeSearchPreferenceTest.kt b/tests/robotests/src/com/android/settings/supervision/SupervisionSafeSearchPreferenceTest.kt
new file mode 100644
index 0000000..371cca3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/supervision/SupervisionSafeSearchPreferenceTest.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2025 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.supervision
+
+import android.content.Context
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.R
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class SupervisionSafeSearchPreferenceTest {
+ private val context: Context = ApplicationProvider.getApplicationContext()
+
+ private val searchFilterOnPreference = SupervisionSearchFilterOnPreference()
+
+ private val searchFilterOffPreference = SupervisionSearchFilterOffPreference()
+
+ @Test
+ fun getTitle_filterOn() {
+ assertThat(searchFilterOnPreference.title)
+ .isEqualTo(R.string.supervision_web_content_filters_search_filter_on_title)
+ }
+
+
+ @Test
+ fun getSummary_filterOn() {
+ assertThat(searchFilterOnPreference.summary)
+ .isEqualTo(R.string.supervision_web_content_filters_search_filter_on_summary)
+ }
+
+ @Test
+ fun getTitle_filterOff() {
+ assertThat(searchFilterOffPreference.title)
+ .isEqualTo(R.string.supervision_web_content_filters_search_filter_off_title)
+ }
+
+ @Test
+ fun getSummary_filterOff() {
+ assertThat(searchFilterOffPreference.summary)
+ .isEqualTo(
+ R.string.supervision_web_content_filters_search_filter_off_summary
+ )
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/supervision/SupervisionSafeSitesPreferenceTest.kt b/tests/robotests/src/com/android/settings/supervision/SupervisionSafeSitesPreferenceTest.kt
index 5be7a11..a3aca69 100644
--- a/tests/robotests/src/com/android/settings/supervision/SupervisionSafeSitesPreferenceTest.kt
+++ b/tests/robotests/src/com/android/settings/supervision/SupervisionSafeSitesPreferenceTest.kt
@@ -16,20 +16,33 @@
package com.android.settings.supervision
import android.content.Context
+import android.provider.Settings
+import android.provider.Settings.Secure.BROWSER_CONTENT_FILTERS_ENABLED
+import android.provider.Settings.SettingNotFoundException
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.R
+import com.android.settingslib.preference.createAndBindWidget
+import com.android.settingslib.widget.SelectorWithWidgetPreference
import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertThrows
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class SupervisionSafeSitesPreferenceTest {
private val context: Context = ApplicationProvider.getApplicationContext()
+ private lateinit var dataStore: SupervisionSafeSitesDataStore
+ private lateinit var allowAllSitesPreference: SupervisionAllowAllSitesPreference
+ private lateinit var blockExplicitSitesPreference: SupervisionBlockExplicitSitesPreference
- private val allowAllSitesPreference = SupervisionAllowAllSitesPreference()
-
- private val blockExplicitSitesPreference = SupervisionBlockExplicitSitesPreference()
+ @Before
+ fun setUp() {
+ dataStore = SupervisionSafeSitesDataStore(context)
+ allowAllSitesPreference = SupervisionAllowAllSitesPreference(dataStore)
+ blockExplicitSitesPreference = SupervisionBlockExplicitSitesPreference(dataStore)
+ }
@Test
fun getTitle_allowAllSites() {
@@ -50,4 +63,64 @@
R.string.supervision_web_content_filters_browser_block_explicit_sites_summary
)
}
+
+ @Test
+ fun allowAllSitesIsChecked_whenNoValueIsSet() {
+ assertThrows(SettingNotFoundException::class.java) {
+ Settings.Secure.getInt(context.getContentResolver(), BROWSER_CONTENT_FILTERS_ENABLED)
+ }
+ assertThat(getBlockExplicitSitesWidget().isChecked).isFalse()
+ assertThat(getAllowAllSitesWidget().isChecked).isTrue()
+ }
+
+ @Test
+ fun blockExplicitSitesIsChecked_whenPreviouslyEnabled() {
+ Settings.Secure.putInt(context.getContentResolver(), BROWSER_CONTENT_FILTERS_ENABLED, 1)
+ assertThat(getAllowAllSitesWidget().isChecked).isFalse()
+ assertThat(getBlockExplicitSitesWidget().isChecked).isTrue()
+ }
+
+ @Test
+ fun clickBlockExplicitSites_enablesFilter() {
+ Settings.Secure.putInt(context.getContentResolver(), BROWSER_CONTENT_FILTERS_ENABLED, 0)
+ val blockExplicitSitesWidget = getBlockExplicitSitesWidget()
+ assertThat(blockExplicitSitesWidget.isChecked).isFalse()
+
+ blockExplicitSitesWidget.performClick()
+
+ assertThat(
+ Settings.Secure.getInt(
+ context.getContentResolver(),
+ BROWSER_CONTENT_FILTERS_ENABLED,
+ )
+ )
+ .isEqualTo(1)
+ assertThat(blockExplicitSitesWidget.isChecked).isTrue()
+ }
+
+ @Test
+ fun clickAllowAllSites_disablesFilter() {
+ Settings.Secure.putInt(context.getContentResolver(), BROWSER_CONTENT_FILTERS_ENABLED, 1)
+ val allowAllSitesWidget = getAllowAllSitesWidget()
+ assertThat(allowAllSitesWidget.isChecked).isFalse()
+
+ allowAllSitesWidget.performClick()
+
+ assertThat(
+ Settings.Secure.getInt(
+ context.getContentResolver(),
+ BROWSER_CONTENT_FILTERS_ENABLED,
+ )
+ )
+ .isEqualTo(0)
+ assertThat(allowAllSitesWidget.isChecked).isTrue()
+ }
+
+ private fun getBlockExplicitSitesWidget(): SelectorWithWidgetPreference {
+ return blockExplicitSitesPreference.createAndBindWidget(context)
+ }
+
+ private fun getAllowAllSitesWidget(): SelectorWithWidgetPreference {
+ return allowAllSitesPreference.createAndBindWidget(context)
+ }
}
diff --git a/tests/robotests/src/com/android/settings/supervision/SupervisionWebContentFiltersScreenTest.kt b/tests/robotests/src/com/android/settings/supervision/SupervisionWebContentFiltersScreenTest.kt
index 351cbde..31bdbd2 100644
--- a/tests/robotests/src/com/android/settings/supervision/SupervisionWebContentFiltersScreenTest.kt
+++ b/tests/robotests/src/com/android/settings/supervision/SupervisionWebContentFiltersScreenTest.kt
@@ -15,18 +15,32 @@
*/
package com.android.settings.supervision
+import android.app.supervision.flags.Flags
import android.content.Context
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.SetFlagsRule
+import androidx.fragment.app.testing.FragmentScenario
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.R
+import com.android.settingslib.widget.SelectorWithWidgetPreference
import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class SupervisionWebContentFiltersScreenTest {
+ @get:Rule val setFlagsRule = SetFlagsRule()
private val context: Context = ApplicationProvider.getApplicationContext()
- private val supervisionWebContentFiltersScreen = SupervisionWebContentFiltersScreen()
+ private lateinit var supervisionWebContentFiltersScreen: SupervisionWebContentFiltersScreen
+
+ @Before
+ fun setUp() {
+ supervisionWebContentFiltersScreen = SupervisionWebContentFiltersScreen()
+ }
@Test
fun key() {
@@ -39,4 +53,40 @@
assertThat(supervisionWebContentFiltersScreen.title)
.isEqualTo(R.string.supervision_web_content_filters_title)
}
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WEB_CONTENT_FILTERS_SCREEN)
+ fun flagEnabled() {
+ assertThat(supervisionWebContentFiltersScreen.isFlagEnabled(context)).isTrue()
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_ENABLE_WEB_CONTENT_FILTERS_SCREEN)
+ fun flagDisabled() {
+ assertThat(supervisionWebContentFiltersScreen.isFlagEnabled(context)).isFalse()
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_WEB_CONTENT_FILTERS_SCREEN)
+ fun switchSafeSitesPreferences() {
+ FragmentScenario.launchInContainer(supervisionWebContentFiltersScreen.fragmentClass())
+ .onFragment { fragment ->
+ val allowAllSitesPreference =
+ fragment.findPreference<SelectorWithWidgetPreference>(
+ SupervisionAllowAllSitesPreference.KEY
+ )!!
+ val blockExplicitSitesPreference =
+ fragment.findPreference<SelectorWithWidgetPreference>(
+ SupervisionBlockExplicitSitesPreference.KEY
+ )!!
+
+ assertThat(allowAllSitesPreference.isChecked).isTrue()
+ assertThat(blockExplicitSitesPreference.isChecked).isFalse()
+
+ blockExplicitSitesPreference.performClick()
+
+ assertThat(blockExplicitSitesPreference.isChecked).isTrue()
+ assertThat(allowAllSitesPreference.isChecked).isFalse()
+ }
+ }
}
diff --git a/tests/unit/src/com/android/settings/safetycenter/FaceSafetySourceTest.java b/tests/unit/src/com/android/settings/safetycenter/FaceSafetySourceTest.java
index 5d94532..1d6f48f 100644
--- a/tests/unit/src/com/android/settings/safetycenter/FaceSafetySourceTest.java
+++ b/tests/unit/src/com/android/settings/safetycenter/FaceSafetySourceTest.java
@@ -37,7 +37,6 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.face.FaceManager;
-import android.hardware.fingerprint.FingerprintManager;
import android.os.UserHandle;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
@@ -53,7 +52,6 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.Settings;
-import com.android.settings.biometrics.BiometricEnrollActivity;
import com.android.settings.biometrics.face.FaceEnrollIntroductionInternal;
import com.android.settings.flags.Flags;
import com.android.settings.testutils.FakeFeatureFactory;
@@ -85,7 +83,6 @@
@Mock private PackageManager mPackageManager;
@Mock private DevicePolicyManager mDevicePolicyManager;
@Mock private FaceManager mFaceManager;
- @Mock private FingerprintManager mFingerprintManager;
@Mock private LockPatternUtils mLockPatternUtils;
@Mock private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper;
@Mock private SupervisionManager mSupervisionManager;
@@ -100,8 +97,6 @@
when(mApplicationContext.getSystemService(Context.DEVICE_POLICY_SERVICE))
.thenReturn(mDevicePolicyManager);
when(mApplicationContext.getSystemService(Context.FACE_SERVICE)).thenReturn(mFaceManager);
- when(mApplicationContext.getSystemService(Context.FINGERPRINT_SERVICE))
- .thenReturn(mFingerprintManager);
when(mApplicationContext.getSystemService(Context.SUPERVISION_SERVICE))
.thenReturn(mSupervisionManager);
FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest();
@@ -216,12 +211,10 @@
@Test
@RequiresFlagsEnabled(Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
- public void setSafetySourceData_onlyFaceNotEnrolled_whenNotDisabledByAdmin_setsData() {
+ public void setSafetySourceData_withFaceNotEnrolled_whenNotDisabledByAdmin_setsData() {
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
when(mFaceManager.isHardwareDetected()).thenReturn(true);
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
- when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
- when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true);
when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0);
FaceSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
@@ -234,24 +227,6 @@
@Test
@RequiresFlagsEnabled(Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
- public void setSafetySourceData_noBiometricEnrolled_whenNotDisabledByAdmin_setsData() {
- when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
- when(mFaceManager.isHardwareDetected()).thenReturn(true);
- when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
- when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
- when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
- when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0);
-
- FaceSafetySource.setSafetySourceData(mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
-
- assertSafetySourceEnabledDataSetWithSingularSummary(
- "security_settings_face_preference_title_new",
- "security_settings_face_preference_summary_none_new",
- BiometricEnrollActivity.class.getName());
- }
-
- @Test
- @RequiresFlagsEnabled(Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
@DisableFlags(android.app.supervision.flags.Flags.FLAG_DEPRECATE_DPM_SUPERVISION_APIS)
public void setSafetySourceData_withFaceEnrolled_whenDisabledByAdmin_setsData() {
when(mDevicePolicyManager.getProfileOwnerOrDeviceOwnerSupervisionComponent(USER_HANDLE))
diff --git a/tests/unit/src/com/android/settings/safetycenter/FingerprintSafetySourceTest.java b/tests/unit/src/com/android/settings/safetycenter/FingerprintSafetySourceTest.java
index 18eae9a..dac2699 100644
--- a/tests/unit/src/com/android/settings/safetycenter/FingerprintSafetySourceTest.java
+++ b/tests/unit/src/com/android/settings/safetycenter/FingerprintSafetySourceTest.java
@@ -36,7 +36,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.hardware.face.FaceManager;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager;
import android.os.UserHandle;
@@ -53,7 +52,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.internal.widget.LockPatternUtils;
-import com.android.settings.biometrics.BiometricEnrollActivity;
import com.android.settings.biometrics.fingerprint.FingerprintSettings;
import com.android.settings.flags.Flags;
import com.android.settings.testutils.FakeFeatureFactory;
@@ -89,7 +87,6 @@
@Mock private PackageManager mPackageManager;
@Mock private DevicePolicyManager mDevicePolicyManager;
@Mock private FingerprintManager mFingerprintManager;
- @Mock private FaceManager mFaceManager;
@Mock private LockPatternUtils mLockPatternUtils;
@Mock private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper;
@Mock private SupervisionManager mSupervisionManager;
@@ -103,7 +100,6 @@
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true);
when(mApplicationContext.getSystemService(Context.FINGERPRINT_SERVICE))
.thenReturn(mFingerprintManager);
- when(mApplicationContext.getSystemService(Context.FACE_SERVICE)).thenReturn(mFaceManager);
when(mApplicationContext.getSystemService(Context.DEVICE_POLICY_SERVICE))
.thenReturn(mDevicePolicyManager);
when(mApplicationContext.getSystemService(Context.SUPERVISION_SERVICE))
@@ -232,12 +228,10 @@
@Test
@RequiresFlagsEnabled(Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
- public void setSafetySourceData_onlyFingerprintNotEnrolled_whenNotDisabledByAdmin_setsData() {
+ public void setSafetySourceData_withFingerprintNotEnrolled_whenNotDisabledByAdmin_setsData() {
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
- when(mFaceManager.isHardwareDetected()).thenReturn(true);
- when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0);
FingerprintSafetySource.setSafetySourceData(
@@ -251,25 +245,6 @@
@Test
@RequiresFlagsEnabled(Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
- public void setSafetySourceData_noBiometricEnrolled_whenNotDisabledByAdmin_setsData() {
- when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
- when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
- when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
- when(mFaceManager.isHardwareDetected()).thenReturn(true);
- when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
- when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0);
-
- FingerprintSafetySource.setSafetySourceData(
- mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
-
- assertSafetySourceEnabledDataSetWithSingularSummary(
- "security_settings_fingerprint",
- "security_settings_fingerprint_preference_summary_none_new",
- BiometricEnrollActivity.class.getName());
- }
-
- @Test
- @RequiresFlagsEnabled(Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
@DisableFlags(android.app.supervision.flags.Flags.FLAG_DEPRECATE_DPM_SUPERVISION_APIS)
public void setSafetySourceData_withFingerprintsEnrolled_whenDisabledByAdmin_setsData() {
int enrolledFingerprintsCount = 2;