Merge "Provide SuspendDialogInfo when quarantining an app." into main
diff --git a/Android.bp b/Android.bp
index 0271b2f..a62aa11 100644
--- a/Android.bp
+++ b/Android.bp
@@ -55,6 +55,9 @@
     ],
 
     srcs: ["src/**/*.java", "src/**/*.kt"],
+    exclude_srcs: [
+        "src/com/android/settings/biometrics/fingerprint2/shared/**/*.kt",
+    ],
     use_resource_processor: true,
     resource_dirs: [
         "res",
@@ -113,6 +116,7 @@
         "SystemUIUnfoldLib",
         "aconfig_settings_flags_lib",
         "android.content.pm.flags-aconfig-java",
+        "FingerprintManagerInteractor",
     ],
 
     plugins: [
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 977c789..95d539a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -641,7 +641,7 @@
     </string>
     <!-- Location settings footer link content description [CHAR LIMIT=NONE] -->
     <string name="location_settings_footer_learn_more_content_description">
-        Learn more about Location Settings.
+        Learn more about Location settings
     </string>
 
     <!-- Main Settings screen setting option title for the item to take you to the accounts screen [CHAR LIMIT=22] -->
@@ -10732,9 +10732,9 @@
     </string-array>
 
     <!-- Debugging developer settings: enable angle as system driver? [CHAR LIMIT=50] -->
-    <string name="enable_angle_as_system_driver">Enable ANGLE</string>
+    <string name="enable_angle_as_system_driver">Experimental: Enable ANGLE</string>
     <!-- Debugging developer settings: enable angle as system driver summary [CHAR LIMIT=NONE] -->
-    <string name="enable_angle_as_system_driver_summary">Enable ANGLE as default OpenGL ES driver. Enabling it on incompatible devices may break some applications.</string>
+    <string name="enable_angle_as_system_driver_summary">Warning: Enable ANGLE as default OpenGL ES driver. This feature is in experiment and may not be compatible with some camera and video apps.</string>
     <!--Dialog body text used to explain a reboot is required after changing ANGLE as system GLES driver setting-->
     <string name="reboot_dialog_enable_angle_as_system_driver">A reboot is required to change the system OpenGL ES driver</string>
 
@@ -12301,6 +12301,10 @@
     <string name="aspect_ratio_summary">Try a new aspect ratio to view this app if it hasn\'t been designed to fit your <xliff:g id="device_name">%1$s</xliff:g></string>
     <!-- [CHAR LIMIT=NONE] Aspect ratio setting main summary on page to choose aspect ratio for apps unoptimized for device -->
     <string name="aspect_ratio_main_summary">Try a new aspect ratio to view this app if it hasn\'t been designed to fit your <xliff:g id="device_name">%1$s</xliff:g>. Some apps may not be optimized for certain aspect ratios.</string>
+    <!-- [CHAR LIMIT=NONE] Aspect ratio setting summary to choose aspect ratio for apps unoptimized for device -->
+    <string name="aspect_ratio_summary_text">Try a new aspect ratio to view an app if it hasn\'t been designed to fit your <xliff:g id="device_name">%1$s</xliff:g></string>
+    <!-- [CHAR LIMIT=NONE] Aspect ratio setting main summary on page to choose aspect ratio for apps unoptimized for device -->
+    <string name="aspect_ratio_main_summary_text">Try a new aspect ratio to view an app if it hasn\'t been designed to fit your <xliff:g id="device_name">%1$s</xliff:g>. Some apps may not be optimized for certain aspect ratios.</string>
     <!-- [CHAR LIMIT=NONE] Aspect ratio suggested apps filter label -->
     <string name="user_aspect_ratio_suggested_apps_label">Suggested apps</string>
     <!-- [CHAR LIMIT=14] Filter label for apps that have user aspect ratio changed -->
diff --git a/res/xml/data_usage_list.xml b/res/xml/data_usage_list.xml
index 791fc86..62456ed 100644
--- a/res/xml/data_usage_list.xml
+++ b/res/xml/data_usage_list.xml
@@ -22,7 +22,9 @@
         android:title="@string/summary_placeholder">
 
         <com.android.settings.datausage.ChartDataUsagePreference
-            android:key="chart_data" />
+            android:key="chart_data"
+            settings:controller="com.android.settings.datausage.ChartDataUsagePreferenceController"
+            />
 
         <Preference
             android:key="non_carrier_data_usage_warning"
diff --git a/res/xml/terms_of_address.xml b/res/xml/terms_of_address.xml
new file mode 100644
index 0000000..a29a55c3
--- /dev/null
+++ b/res/xml/terms_of_address.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:title="@string/terms_of_address_title">
+
+    <com.android.settingslib.widget.TopIntroPreference
+        android:title="@string/terms_of_address_intro_title"
+        android:persistent="false"/>
+
+    <com.android.settings.widget.TickButtonPreference
+        android:key="key_terms_of_address_not_specified"
+        android:title="@string/terms_of_address_not_specified"
+        settings:controller="com.android.settings.localepicker.TermsOfAddressNotSpecifiedController"/>
+
+    <com.android.settings.widget.TickButtonPreference
+        android:key="key_terms_of_address_feminine"
+        android:title="@string/terms_of_address_feminine"
+        settings:controller="com.android.settings.localepicker.TermsOfAddressFeminineController"/>
+
+    <com.android.settings.widget.TickButtonPreference
+        android:key="key_terms_of_address_masculine"
+        android:title="@string/terms_of_address_masculine"
+        settings:controller="com.android.settings.localepicker.TermsOfAddressMasculineController"/>
+
+    <com.android.settings.widget.TickButtonPreference
+        android:key="key_terms_of_address_neutral"
+        android:title="@string/terms_of_address_neutral"
+        settings:controller="com.android.settings.localepicker.TermsOfAddressNeutralController"/>
+
+</PreferenceScreen>
diff --git a/src/com/android/settings/accessibility/LockScreenRotationPreferenceController.java b/src/com/android/settings/accessibility/LockScreenRotationPreferenceController.java
index db19096..bde2ef5 100644
--- a/src/com/android/settings/accessibility/LockScreenRotationPreferenceController.java
+++ b/src/com/android/settings/accessibility/LockScreenRotationPreferenceController.java
@@ -54,7 +54,8 @@
      */
     @Override
     public boolean setChecked(boolean isChecked) {
-        RotationPolicy.setRotationLock(mContext, !isChecked);
+        RotationPolicy.setRotationLock(mContext, !isChecked,
+                /* caller= */ "LockScreenRotationPreferenceController#setChecked");
         return true;
     }
 
diff --git a/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java b/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java
index 2c157c4..b940dc8 100644
--- a/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java
+++ b/src/com/android/settings/applications/appcompat/UserAspectRatioManager.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.applications.appcompat;
 
+import static android.os.UserHandle.getUserHandleForUid;
 import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE;
 import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE;
 
@@ -26,8 +27,8 @@
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
+import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.os.RemoteException;
 import android.provider.DeviceConfig;
 import android.util.ArrayMap;
@@ -40,7 +41,6 @@
 
 import com.google.common.annotations.VisibleForTesting;
 
-import java.util.List;
 import java.util.Map;
 
 /**
@@ -63,15 +63,12 @@
     private final Context mContext;
     private final IPackageManager mIPm;
     /** Apps that have launcher entry defined in manifest */
-    private final List<ResolveInfo> mInfoHasLauncherEntryList;
     private final Map<Integer, String> mUserAspectRatioMap;
     private final Map<Integer, CharSequence> mUserAspectRatioA11yMap;
 
     public UserAspectRatioManager(@NonNull Context context) {
         mContext = context;
         mIPm = AppGlobals.getPackageManager();
-        mInfoHasLauncherEntryList = mContext.getPackageManager().queryIntentActivities(
-                UserAspectRatioManager.LAUNCHER_ENTRY_INTENT, PackageManager.GET_META_DATA);
         mUserAspectRatioA11yMap = new ArrayMap<>();
         mUserAspectRatioMap = getUserMinAspectRatioMapping();
     }
@@ -159,9 +156,7 @@
         Boolean appAllowsUserAspectRatioOverride = readComponentProperty(
                 mContext.getPackageManager(), app.packageName,
                 PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE);
-        boolean hasLauncherEntry = mInfoHasLauncherEntryList.stream()
-                .anyMatch(info -> info.activityInfo.packageName.equals(app.packageName));
-        return !FALSE.equals(appAllowsUserAspectRatioOverride) && hasLauncherEntry;
+        return !FALSE.equals(appAllowsUserAspectRatioOverride) && hasLauncherEntry(app);
     }
 
     /**
@@ -178,6 +173,15 @@
                     DEFAULT_VALUE_ENABLE_USER_ASPECT_RATIO_FULLSCREEN);
     }
 
+    LauncherApps getLauncherApps() {
+        return mContext.getSystemService(LauncherApps.class);
+    }
+
+    private boolean hasLauncherEntry(@NonNull ApplicationInfo app) {
+        return !getLauncherApps().getActivityList(app.packageName, getUserHandleForUid(app.uid))
+                .isEmpty();
+    }
+
     private static boolean getValueFromDeviceConfig(String name, boolean defaultValue) {
         return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER, name, defaultValue);
     }
@@ -267,9 +271,4 @@
         }
         return null;
     }
-
-    @VisibleForTesting
-    void addInfoHasLauncherEntry(@NonNull ResolveInfo infoHasLauncherEntry) {
-        mInfoHasLauncherEntryList.add(infoHasLauncherEntry);
-    }
 }
diff --git a/src/com/android/settings/biometrics/fingerprint2/conversion/Util.kt b/src/com/android/settings/biometrics/fingerprint2/conversion/Util.kt
new file mode 100644
index 0000000..b2767c3
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint2/conversion/Util.kt
@@ -0,0 +1,62 @@
+/*
+ * 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.biometrics.fingerprint2.conversion
+
+import android.hardware.fingerprint.FingerprintManager
+import android.hardware.fingerprint.FingerprintSensorProperties
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
+import com.android.settings.biometrics.fingerprint2.shared.model.EnrollReason
+import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintSensorPropertyViewModel
+import com.android.settings.biometrics.fingerprint2.shared.model.SensorStrength
+import com.android.settings.biometrics.fingerprint2.shared.model.SensorType
+
+class Util {
+  companion object {
+    fun sensorPropsToViewModel(
+      props: FingerprintSensorPropertiesInternal
+    ): FingerprintSensorPropertyViewModel {
+      val sensorStrength: SensorStrength =
+        when (props.sensorStrength) {
+          FingerprintSensorProperties.STRENGTH_CONVENIENCE -> SensorStrength.Convenient
+          FingerprintSensorProperties.STRENGTH_WEAK -> SensorStrength.Weak
+          FingerprintSensorProperties.STRENGTH_STRONG -> SensorStrength.Strong
+          else -> SensorStrength.Unknown
+        }
+      val sensorType: SensorType =
+        when (props.sensorType) {
+          FingerprintSensorProperties.TYPE_UDFPS_OPTICAL -> SensorType.Optical
+          FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC -> SensorType.Ultrasonic
+          FingerprintSensorProperties.TYPE_REAR -> SensorType.RFPS
+          FingerprintSensorProperties.TYPE_POWER_BUTTON -> SensorType.SFPS
+          else -> SensorType.Unknown
+        }
+      return FingerprintSensorPropertyViewModel(
+        props.sensorId,
+        sensorStrength,
+        props.maxEnrollmentsPerUser,
+        sensorType
+      )
+    }
+  }
+
+}
+fun EnrollReason.toOriginalReason(): Int {
+  return when (this) {
+    EnrollReason.EnrollEnrolling -> FingerprintManager.ENROLL_ENROLL
+    EnrollReason.FindSensor -> FingerprintManager.ENROLL_FIND_SENSOR
+  }
+}
diff --git a/src/com/android/settings/biometrics/fingerprint2/domain/interactor/FingerprintManagerInteractor.kt b/src/com/android/settings/biometrics/fingerprint2/domain/interactor/FingerprintManagerInteractorImpl.kt
similarity index 75%
rename from src/com/android/settings/biometrics/fingerprint2/domain/interactor/FingerprintManagerInteractor.kt
rename to src/com/android/settings/biometrics/fingerprint2/domain/interactor/FingerprintManagerInteractorImpl.kt
index 2c8ee8f..41da247 100644
--- a/src/com/android/settings/biometrics/fingerprint2/domain/interactor/FingerprintManagerInteractor.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/domain/interactor/FingerprintManagerInteractorImpl.kt
@@ -21,15 +21,16 @@
 import android.hardware.fingerprint.FingerprintManager
 import android.hardware.fingerprint.FingerprintManager.GenerateChallengeCallback
 import android.hardware.fingerprint.FingerprintManager.RemovalCallback
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
 import android.os.CancellationSignal
 import android.util.Log
 import com.android.settings.biometrics.GatekeeperPasswordProvider
+import com.android.settings.biometrics.fingerprint2.conversion.Util
+import com.android.settings.biometrics.fingerprint2.conversion.toOriginalReason
+import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
+import com.android.settings.biometrics.fingerprint2.shared.model.EnrollReason
 import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptViewModel
 import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintViewModel
-import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.EnrollReason
-import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerEnrollStateViewModel
-import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.toOriginalReason
+import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollStateViewModel
 import com.android.settings.password.ChooseLockSettingsHelper
 import kotlin.coroutines.resume
 import kotlin.coroutines.suspendCoroutine
@@ -45,59 +46,6 @@
 
 private const val TAG = "FingerprintManagerInteractor"
 
-/** Encapsulates business logic related to managing fingerprints. */
-interface FingerprintManagerInteractor {
-  /** Returns the list of current fingerprints. */
-  val enrolledFingerprints: Flow<List<FingerprintViewModel>>
-
-  /** Returns the max enrollable fingerprints, note during SUW this might be 1 */
-  val maxEnrollableFingerprints: Flow<Int>
-
-  /** Returns true if a user can enroll a fingerprint false otherwise. */
-  val canEnrollFingerprints: Flow<Boolean>
-
-  /** Retrieves the sensor properties of a device */
-  val sensorPropertiesInternal: Flow<FingerprintSensorPropertiesInternal?>
-
-  /** Runs [FingerprintManager.authenticate] */
-  suspend fun authenticate(): FingerprintAuthAttemptViewModel
-
-  /**
-   * Generates a challenge with the provided [gateKeeperPasswordHandle] and on success returns a
-   * challenge and challenge token. This info can be used for secure operations such as
-   * [FingerprintManager.enroll]
-   *
-   * @param gateKeeperPasswordHandle GateKeeper password handle generated by a Confirm
-   * @return A [Pair] of the challenge and challenge token
-   */
-  suspend fun generateChallenge(gateKeeperPasswordHandle: Long): Pair<Long, ByteArray>
-
-  /**
-   * Runs [FingerprintManager.enroll] with the [hardwareAuthToken] and [EnrollReason] for this
-   * enrollment. Returning the [FingerEnrollStateViewModel] that represents this fingerprint
-   * enrollment state.
-   */
-  suspend fun enroll(
-    hardwareAuthToken: ByteArray?,
-    enrollReason: EnrollReason,
-  ): Flow<FingerEnrollStateViewModel>
-
-  /**
-   * Removes the given fingerprint, returning true if it was successfully removed and false
-   * otherwise
-   */
-  suspend fun removeFingerprint(fp: FingerprintViewModel): Boolean
-
-  /** Renames the given fingerprint if one exists */
-  suspend fun renameFingerprint(fp: FingerprintViewModel, newName: String)
-
-  /** Indicates if the device has side fingerprint */
-  suspend fun hasSideFps(): Boolean
-
-  /** Indicates if the press to auth feature has been enabled */
-  suspend fun pressToAuthEnabled(): Boolean
-}
-
 class FingerprintManagerInteractorImpl(
   applicationContext: Context,
   private val backgroundDispatcher: CoroutineDispatcher,
@@ -144,7 +92,10 @@
 
   override val sensorPropertiesInternal = flow {
     val sensorPropertiesInternal = fingerprintManager.sensorPropertiesInternal
-    emit(if (sensorPropertiesInternal.isEmpty()) null else sensorPropertiesInternal.first())
+    emit(
+      if (sensorPropertiesInternal.isEmpty()) null
+      else Util.sensorPropsToViewModel(sensorPropertiesInternal.first())
+    )
   }
 
   override val maxEnrollableFingerprints = flow { emit(maxFingerprints) }
@@ -183,7 +134,7 @@
       cancellationSignal,
       applicationContext.userId,
       enrollmentCallback,
-      enrollReason.toOriginalReason()
+      enrollReason.toOriginalReason(),
     )
     awaitClose {
       // If the stream has not been ended, and the user has stopped collecting the flow
diff --git a/src/com/android/settings/biometrics/fingerprint2/shared/Android.bp b/src/com/android/settings/biometrics/fingerprint2/shared/Android.bp
new file mode 100644
index 0000000..8873fd8
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint2/shared/Android.bp
@@ -0,0 +1,13 @@
+// This  library is mainly used for fakes which will be shared across are various types of tests
+// unit/robo/screenshot etc.
+//
+// This library shouldn't have many dependencies.
+android_library {
+    name: "FingerprintManagerInteractor",
+    srcs: [
+      "**/*.kt"
+    ],
+    static_libs: [
+      "kotlinx-coroutines-android",
+    ],
+}
\ No newline at end of file
diff --git a/src/com/android/settings/biometrics/fingerprint2/shared/AndroidManifest.xml b/src/com/android/settings/biometrics/fingerprint2/shared/AndroidManifest.xml
new file mode 100644
index 0000000..e2c97fc
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint2/shared/AndroidManifest.xml
@@ -0,0 +1,18 @@
+<!--
+  ~ 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.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.settings.biometrics.fingerprint2.shared">
+</manifest>
diff --git a/src/com/android/settings/biometrics/fingerprint2/shared/domain/interactor/FingerprintManagerInteractor.kt b/src/com/android/settings/biometrics/fingerprint2/shared/domain/interactor/FingerprintManagerInteractor.kt
new file mode 100644
index 0000000..5353bb2
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint2/shared/domain/interactor/FingerprintManagerInteractor.kt
@@ -0,0 +1,82 @@
+/*
+ * 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.biometrics.fingerprint2.shared.domain.interactor
+
+import com.android.settings.biometrics.fingerprint2.shared.model.EnrollReason
+import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptViewModel
+import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintSensorPropertyViewModel
+import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintViewModel
+import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollStateViewModel
+import kotlinx.coroutines.flow.Flow
+
+/**
+ * Interface to obtain the necessary data for FingerprintEnrollment/Settings
+ *
+ * Note that this interface should not have dependencies on heavyweight libraries such as the
+ * framework, hidl/aidl, etc. This makes it much easier to test and create fakes for.
+ */
+interface FingerprintManagerInteractor {
+  /** Returns the list of current fingerprints. */
+  val enrolledFingerprints: Flow<List<FingerprintViewModel>>
+
+  /** Returns the max enrollable fingerprints, note during SUW this might be 1 */
+  val maxEnrollableFingerprints: Flow<Int>
+
+  /** Returns true if a user can enroll a fingerprint false otherwise. */
+  val canEnrollFingerprints: Flow<Boolean>
+
+  /** Retrieves the sensor properties of a device */
+  val sensorPropertiesInternal: Flow<FingerprintSensorPropertyViewModel?>
+
+  /** Runs the authenticate flow */
+  suspend fun authenticate(): FingerprintAuthAttemptViewModel
+
+  /**
+   * Generates a challenge with the provided [gateKeeperPasswordHandle] and on success returns a
+   * challenge and challenge token. This info can be used for secure operations such as enrollment
+   *
+   * @param gateKeeperPasswordHandle GateKeeper password handle generated by a Confirm
+   * @return A [Pair] of the challenge and challenge token
+   */
+  suspend fun generateChallenge(gateKeeperPasswordHandle: Long): Pair<Long, ByteArray>
+
+  /**
+   * Runs [FingerprintManager.enroll] with the [hardwareAuthToken] and [EnrollReason] for this
+   * enrollment. Returning the [FingerEnrollStateViewModel] that represents this fingerprint
+   * enrollment state.
+   */
+  suspend fun enroll(
+    hardwareAuthToken: ByteArray?,
+    enrollReason: EnrollReason,
+  ): Flow<FingerEnrollStateViewModel>
+
+  /**
+   * Removes the given fingerprint, returning true if it was successfully removed and false
+   * otherwise
+   */
+  suspend fun removeFingerprint(fp: FingerprintViewModel): Boolean
+
+  /** Renames the given fingerprint if one exists */
+  suspend fun renameFingerprint(fp: FingerprintViewModel, newName: String)
+
+  /** Indicates if the device has side fingerprint */
+  suspend fun hasSideFps(): Boolean
+
+  /** Indicates if the press to auth feature has been enabled */
+  suspend fun pressToAuthEnabled(): Boolean
+
+}
diff --git a/src/com/android/settings/biometrics/fingerprint2/shared/model/EnrollReasonViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/shared/model/EnrollReasonViewModel.kt
new file mode 100644
index 0000000..47a0af0
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint2/shared/model/EnrollReasonViewModel.kt
@@ -0,0 +1,28 @@
+/*
+ * 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.biometrics.fingerprint2.shared.model
+
+/** The reason for enrollment */
+enum class EnrollReason {
+  /**
+   * The enroll happens on education screen. This is to support legacy flows where we require the
+   * user to touch the sensor before going ahead to the EnrollEnrolling flow
+   */
+  FindSensor,
+  /** The enroll happens on enrolling screen. */
+  EnrollEnrolling
+}
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerEnrollStateViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/shared/model/FingerEnrollStateViewModel.kt
similarity index 94%
rename from src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerEnrollStateViewModel.kt
rename to src/com/android/settings/biometrics/fingerprint2/shared/model/FingerEnrollStateViewModel.kt
index 73343bd..179ac60 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerEnrollStateViewModel.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/shared/model/FingerEnrollStateViewModel.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
+package com.android.settings.biometrics.fingerprint2.shared.model
 
 import android.annotation.StringRes
 
diff --git a/src/com/android/settings/biometrics/fingerprint2/shared/model/FingerprintViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/shared/model/FingerprintViewModel.kt
index db28e79..fc9539c 100644
--- a/src/com/android/settings/biometrics/fingerprint2/shared/model/FingerprintViewModel.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/shared/model/FingerprintViewModel.kt
@@ -32,3 +32,36 @@
     val message: String,
   ) : FingerprintAuthAttemptViewModel()
 }
+
+/** The various types of fingerprint sensors */
+sealed class SensorType {
+  /** Rear fingerprint sensor */
+  data object RFPS : SensorType()
+
+  /** Optical under display sensor */
+  data object Optical : SensorType()
+
+  /** Ultrasonic under display sensor */
+  data object Ultrasonic : SensorType()
+
+  /** Side fingerprint sensor */
+  data object SFPS : SensorType()
+
+  /** Unkonwn fingerprint sensor */
+  data object Unknown : SensorType()
+}
+
+/** The strength of a given sensor */
+sealed class SensorStrength {
+  data object Convenient : SensorStrength()
+  data object Weak : SensorStrength()
+  data object Strong : SensorStrength()
+  data object Unknown : SensorStrength()
+}
+
+data class FingerprintSensorPropertyViewModel(
+  val sensorId: Int,
+  val sensorStrength: SensorStrength,
+  val maxEnrollmentsPerUser: Int,
+  val sensorType: SensorType
+)
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/fragment/FingerprintEnrollFindSensorV2Fragment.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/fragment/FingerprintEnrollFindSensorV2Fragment.kt
index dcdcccf..e4ac00f 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/fragment/FingerprintEnrollFindSensorV2Fragment.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/fragment/FingerprintEnrollFindSensorV2Fragment.kt
@@ -29,6 +29,7 @@
 import com.android.settings.R
 import com.android.settings.biometrics.fingerprint.FingerprintErrorDialog
 import com.android.settings.biometrics.fingerprint.FingerprintFindSensorAnimation
+import com.android.settings.biometrics.fingerprint2.shared.model.SensorType
 import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollFindSensorViewModel
 import com.android.systemui.biometrics.shared.model.FingerprintSensorType
 import com.google.android.setupcompat.template.FooterBarMixin
@@ -65,9 +66,9 @@
       viewModel.sensorType.collect {
         contentLayoutId =
           when (it) {
-            FingerprintSensorType.UDFPS_OPTICAL,
-            FingerprintSensorType.UDFPS_ULTRASONIC -> R.layout.udfps_enroll_find_sensor_layout
-            FingerprintSensorType.POWER_BUTTON -> R.layout.sfps_enroll_find_sensor_layout
+            SensorType.Optical,
+            SensorType.Ultrasonic -> R.layout.udfps_enroll_find_sensor_layout
+            SensorType.SFPS -> R.layout.sfps_enroll_find_sensor_layout
             else -> R.layout.fingerprint_v2_enroll_find_sensor
           }
       }
@@ -170,14 +171,14 @@
     illustrationLottie?.visibility = View.VISIBLE
   }
 
-  private fun setTexts(sensorType: FingerprintSensorType, view: GlifLayout) {
+  private fun setTexts(sensorType: SensorType, view: GlifLayout) {
     when (sensorType) {
-      FingerprintSensorType.UDFPS_OPTICAL,
-      FingerprintSensorType.UDFPS_ULTRASONIC -> {
+      SensorType.Optical,
+      SensorType.Ultrasonic -> {
         view.setHeaderText(R.string.security_settings_udfps_enroll_find_sensor_title)
         view.setDescriptionText(R.string.security_settings_udfps_enroll_find_sensor_message)
       }
-      FingerprintSensorType.POWER_BUTTON -> {
+      SensorType.SFPS -> {
         view.setHeaderText(R.string.security_settings_sfps_enroll_find_sensor_title)
         view.setDescriptionText(R.string.security_settings_sfps_enroll_find_sensor_message)
       }
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/fragment/FingerprintEnrollIntroV2Fragment.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/fragment/FingerprintEnrollIntroV2Fragment.kt
index dbf6d12..2ebc5d5 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/fragment/FingerprintEnrollIntroV2Fragment.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/fragment/FingerprintEnrollIntroV2Fragment.kt
@@ -35,10 +35,10 @@
 import com.android.settings.R
 import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollNavigationViewModel
 import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollViewModel
+import com.android.settings.biometrics.fingerprint2.shared.model.SensorType
 import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
 import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintScrollViewModel
 import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Unicorn
-import com.android.systemui.biometrics.shared.model.FingerprintSensorType
 import com.google.android.setupcompat.template.FooterBarMixin
 import com.google.android.setupcompat.template.FooterButton
 import com.google.android.setupdesign.GlifLayout
@@ -144,8 +144,8 @@
             val iconShield: ImageView = view.requireViewById(R.id.icon_shield)
             val footerMessage6: TextView = view.requireViewById(R.id.footer_message_6)
             when (sensorType) {
-              FingerprintSensorType.UDFPS_ULTRASONIC,
-              FingerprintSensorType.UDFPS_OPTICAL -> {
+              SensorType.Ultrasonic,
+              SensorType.Optical -> {
                 footerMessage6.visibility = View.VISIBLE
                 iconShield.visibility = View.VISIBLE
               }
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/EnrollReason.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/EnrollReason.kt
deleted file mode 100644
index 87deeb3..0000000
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/EnrollReason.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.biometrics.fingerprint2.ui.enrollment.viewmodel
-
-import android.hardware.fingerprint.FingerprintManager
-
-/**
- * The reason for enrollment. Represents [FingerprintManager.EnrollReason]
- */
-enum class EnrollReason {
-  /** The enroll happens on education screen. */
-  FindSensor,
-  /** The enroll happens on enrolling screen. */
-  EnrollEnrolling
-}
-
-/** Convert EnrollReason to original [FingerprintManager.EnrollReason]. */
-fun EnrollReason.toOriginalReason(): Int {
-  return when (this) {
-    EnrollReason.EnrollEnrolling -> FingerprintManager.ENROLL_ENROLL
-    EnrollReason.FindSensor -> FingerprintManager.ENROLL_FIND_SENSOR
-  }
-}
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollFindSensorViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollFindSensorViewModel.kt
index dbf6b33..c877d67 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollFindSensorViewModel.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollFindSensorViewModel.kt
@@ -20,6 +20,9 @@
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
 import androidx.lifecycle.viewModelScope
+import com.android.settings.biometrics.fingerprint2.shared.model.EnrollReason
+import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollStateViewModel
+import com.android.settings.biometrics.fingerprint2.shared.model.SensorType
 import com.android.systemui.biometrics.shared.model.FingerprintSensorType
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -42,13 +45,13 @@
   orientationStateViewModel: OrientationStateViewModel
 ) : ViewModel() {
   /** Represents the stream of sensor type. */
-  val sensorType: Flow<FingerprintSensorType> =
+  val sensorType: Flow<SensorType> =
     fingerprintEnrollViewModel.sensorType.filterWhenEducationIsShown()
   private val _isUdfps: Flow<Boolean> =
     sensorType.map {
-      it == FingerprintSensorType.UDFPS_OPTICAL || it == FingerprintSensorType.UDFPS_ULTRASONIC
+      it == SensorType.Optical || it == SensorType.Ultrasonic
     }
-  private val _isSfps: Flow<Boolean> = sensorType.map { it == FingerprintSensorType.POWER_BUTTON }
+  private val _isSfps: Flow<Boolean> = sensorType.map { it == SensorType.RFPS }
   private val _isRearSfps: Flow<Boolean> =
     combineTransform(_isSfps, _isUdfps) { v1, v2 -> !v1 && !v2 }
 
@@ -92,8 +95,8 @@
         ) { sensorType, hasValidGatekeeperInfo, gatekeeperInfo, navigationViewModel ->
           val shouldStartEnroll =
             navigationViewModel.currStep == Education &&
-              sensorType != FingerprintSensorType.UDFPS_OPTICAL &&
-              sensorType != FingerprintSensorType.UDFPS_ULTRASONIC &&
+              sensorType != SensorType.Optical &&
+              sensorType != SensorType.Ultrasonic &&
               hasValidGatekeeperInfo
           if (shouldStartEnroll) (gatekeeperInfo as GatekeeperInfo.GatekeeperPasswordInfo).token
           else null
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollViewModel.kt
index cb1beb9..b2c51db 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollViewModel.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollViewModel.kt
@@ -17,13 +17,14 @@
 
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
-import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractor
+import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
+import com.android.settings.biometrics.fingerprint2.shared.model.EnrollReason
+import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollStateViewModel
+import com.android.settings.biometrics.fingerprint2.shared.model.SensorType
 import com.android.systemui.biometrics.shared.model.FingerprintSensorType
-import com.android.systemui.biometrics.shared.model.toSensorType
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.filterNotNull
 import kotlinx.coroutines.flow.flowOn
@@ -39,17 +40,15 @@
   backgroundDispatcher: CoroutineDispatcher,
 ) : ViewModel() {
 
-  /** Represents the stream of [FingerprintSensorType] */
-  val sensorType: Flow<FingerprintSensorType> =
-    fingerprintManagerInteractor.sensorPropertiesInternal.filterNotNull().map {
-      it.sensorType.toSensorType()
-    }
-
   private var _enrollReason: MutableStateFlow<EnrollReason> =
     MutableStateFlow(EnrollReason.FindSensor)
   private var _hardwareAuthToken: MutableStateFlow<ByteArray?> = MutableStateFlow(null)
   private var _consumerShouldEnroll: MutableStateFlow<Boolean> = MutableStateFlow(false)
 
+  /** Represents the stream of [FingerprintSensorType] */
+  val sensorType: Flow<SensorType> =
+    fingerprintManagerInteractor.sensorPropertiesInternal.filterNotNull().map { it.sensorType }
+
   /**
    * A flow that contains a [FingerprintEnrollViewModel] which contains the relevant information for
    * an enrollment process
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrolllNavigationViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrolllNavigationViewModel.kt
index dafe545..d2bb321 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrolllNavigationViewModel.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrolllNavigationViewModel.kt
@@ -20,7 +20,7 @@
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
 import androidx.lifecycle.viewModelScope
-import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractor
+import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -39,7 +39,7 @@
 /**
  * The [EnrollType] for fingerprint enrollment indicates information on how the flow should behave.
  */
-sealed class EnrollType()
+sealed class EnrollType
 
 /** The default enrollment experience, typically called from Settings */
 object Default : EnrollType()
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintGatekeeperViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintGatekeeperViewModel.kt
index fa4463a..db93d02 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintGatekeeperViewModel.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintGatekeeperViewModel.kt
@@ -21,7 +21,7 @@
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
 import androidx.lifecycle.viewModelScope
-import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractor
+import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.asStateFlow
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintScrollViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintScrollViewModel.kt
index d79d9c0..989d4d3 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintScrollViewModel.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintScrollViewModel.kt
@@ -27,6 +27,7 @@
 class FingerprintScrollViewModel : ViewModel() {
 
   private val _hasReadConsentScreen: MutableStateFlow<Boolean> = MutableStateFlow(false)
+
   /** Indicates if a user has consented to FingerprintEnrollment */
   val hasReadConsentScreen: Flow<Boolean> = _hasReadConsentScreen.asStateFlow()
 
@@ -35,7 +36,7 @@
     _hasReadConsentScreen.update { true }
   }
 
-  class FingerprintScrollViewModelFactory() : ViewModelProvider.Factory {
+  class FingerprintScrollViewModelFactory : ViewModelProvider.Factory {
 
     @Suppress("UNCHECKED_CAST")
     override fun <T : ViewModel> create(
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/settings/binder/FingerprintSettingsViewBinder.kt b/src/com/android/settings/biometrics/fingerprint2/ui/settings/binder/FingerprintSettingsViewBinder.kt
index 9f42d81..e66b4cd 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/settings/binder/FingerprintSettingsViewBinder.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/settings/binder/FingerprintSettingsViewBinder.kt
@@ -34,7 +34,6 @@
 import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.ShowSettings
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.Job
-import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.flow.filterNotNull
 import kotlinx.coroutines.launch
@@ -55,7 +54,6 @@
       challenge: Long?,
       challengeToken: ByteArray?
     )
-
     /** Helper to launch an add fingerprint request */
     fun launchAddFingerprint(userId: Int, challengeToken: ByteArray?)
     /**
@@ -63,10 +61,8 @@
      * choose a PIN/PATTERN/PASS.
      */
     fun launchConfirmOrChooseLock(userId: Int)
-
     /** Used to indicate that FingerprintSettings is finished. */
     fun finish()
-
     /** Indicates what result should be set for the returning callee */
     fun setResultExternal(resultCode: Int)
     /** Indicates the settings UI should be shown */
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/settings/fragment/FingerprintSettingsRenameDialog.kt b/src/com/android/settings/biometrics/fingerprint2/ui/settings/fragment/FingerprintSettingsRenameDialog.kt
index 84f33ff..9bde0b0 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/settings/fragment/FingerprintSettingsRenameDialog.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/settings/fragment/FingerprintSettingsRenameDialog.kt
@@ -106,8 +106,9 @@
         val dialog = FingerprintSettingsRenameDialog()
         val onClick =
           DialogInterface.OnClickListener { _, _ ->
-            val dialogTextField = dialog.requireDialog()
-                .requireViewById(R.id.fingerprint_rename_field) as ImeAwareEditText
+            val dialogTextField =
+              dialog.requireDialog().requireViewById(R.id.fingerprint_rename_field)
+                as ImeAwareEditText
             val newName = dialogTextField.text.toString()
             if (!TextUtils.equals(newName, fp.name)) {
               Log.d(TAG, "rename $fp.name to $newName for $dialog")
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/settings/viewmodel/FingerprintSettingsNavigationViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/settings/viewmodel/FingerprintSettingsNavigationViewModel.kt
index 538bb6d..22a25e1 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/settings/viewmodel/FingerprintSettingsNavigationViewModel.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/settings/viewmodel/FingerprintSettingsNavigationViewModel.kt
@@ -21,7 +21,7 @@
 import androidx.lifecycle.ViewModelProvider
 import androidx.lifecycle.viewModelScope
 import com.android.settings.biometrics.BiometricEnrollBase
-import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractor
+import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
@@ -32,17 +32,18 @@
 
 /** A Viewmodel that represents the navigation of the FingerprintSettings activity. */
 class FingerprintSettingsNavigationViewModel(
-  private val userId: Int,
-  private val fingerprintManagerInteractor: FingerprintManagerInteractor,
-  private val backgroundDispatcher: CoroutineDispatcher,
-  tokenInit: ByteArray?,
-  challengeInit: Long?,
+    private val userId: Int,
+    private val fingerprintManagerInteractor: FingerprintManagerInteractor,
+    private val backgroundDispatcher: CoroutineDispatcher,
+    tokenInit: ByteArray?,
+    challengeInit: Long?,
 ) : ViewModel() {
 
   private var token = tokenInit
   private var challenge = challengeInit
 
   private val _nextStep: MutableStateFlow<NextStepViewModel?> = MutableStateFlow(null)
+
   /** This flow represents the high level state for the FingerprintSettingsV2Fragment. */
   val nextStep: StateFlow<NextStepViewModel?> = _nextStep.asStateFlow()
 
@@ -118,8 +119,8 @@
       launchFinishSettings("Error, empty keyChallenge")
       return
     }
-    token = theToken!!
-    challenge = theChallenge!!
+    token = theToken
+    challenge = theChallenge
 
     showSettingsHelper()
   }
@@ -170,12 +171,13 @@
   private fun launchFinishSettings(reason: String, errorCode: Int) {
     _nextStep.update { FinishSettingsWithResult(errorCode, reason) }
   }
+
   class FingerprintSettingsNavigationModelFactory(
-    private val userId: Int,
-    private val interactor: FingerprintManagerInteractor,
-    private val backgroundDispatcher: CoroutineDispatcher,
-    private val token: ByteArray?,
-    private val challenge: Long?,
+      private val userId: Int,
+      private val interactor: FingerprintManagerInteractor,
+      private val backgroundDispatcher: CoroutineDispatcher,
+      private val token: ByteArray?,
+      private val challenge: Long?,
   ) : ViewModelProvider.Factory {
 
     @Suppress("UNCHECKED_CAST")
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/settings/viewmodel/FingerprintSettingsViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/settings/viewmodel/FingerprintSettingsViewModel.kt
index 5770d09..d2691b4 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/settings/viewmodel/FingerprintSettingsViewModel.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/settings/viewmodel/FingerprintSettingsViewModel.kt
@@ -21,11 +21,10 @@
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
 import androidx.lifecycle.viewModelScope
-import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractor
+import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
 import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptViewModel
 import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintViewModel
-import com.android.systemui.biometrics.shared.model.FingerprintSensorType
-import com.android.systemui.biometrics.shared.model.toSensorType
+import com.android.settings.biometrics.fingerprint2.shared.model.SensorType
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableSharedFlow
@@ -90,10 +89,8 @@
 
   private val _consumerShouldAuthenticate: MutableStateFlow<Boolean> = MutableStateFlow(false)
 
-  private val _fingerprintSensorType: Flow<FingerprintSensorType> =
-    fingerprintManagerInteractor.sensorPropertiesInternal.filterNotNull().map {
-      it.sensorType.toSensorType()
-    }
+  private val _fingerprintSensorType: Flow<SensorType> =
+    fingerprintManagerInteractor.sensorPropertiesInternal.filterNotNull().map { it.sensorType }
 
   private val _sensorNullOrEmpty: Flow<Boolean> =
     fingerprintManagerInteractor.sensorPropertiesInternal.map { it == null }
@@ -149,10 +146,7 @@
         if (sensorNullOrEmpty) {
           return@combine false
         }
-        if (
-          listOf(FingerprintSensorType.UDFPS_ULTRASONIC, FingerprintSensorType.UDFPS_OPTICAL)
-            .contains(sensorType)
-        ) {
+        if (listOf(SensorType.Ultrasonic, SensorType.Optical).contains(sensorType)) {
           return@combine false
         }
 
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
index 8a7c048..cfe7962 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
@@ -203,6 +203,16 @@
         slicePreferenceController.setSliceUri(sliceEnabled ? controlUri : null);
         slicePreferenceController.onStart();
         slicePreferenceController.displayPreference(getPreferenceScreen());
+
+        // Temporarily fix the issue that the page will be automatically scrolled to a wrong
+        // position when entering the page. This will make sure the bluetooth header is shown on top
+        // of the page.
+        use(LeAudioBluetoothDetailsHeaderController.class).displayPreference(
+                getPreferenceScreen());
+        use(AdvancedBluetoothDetailsHeaderController.class).displayPreference(
+                getPreferenceScreen());
+        use(BluetoothDetailsHeaderController.class).displayPreference(
+                getPreferenceScreen());
     }
 
     private final ViewTreeObserver.OnGlobalLayoutListener mOnGlobalLayoutListener =
diff --git a/src/com/android/settings/datausage/AppDataUsage.java b/src/com/android/settings/datausage/AppDataUsage.java
index c3be0aa..33307a3 100644
--- a/src/com/android/settings/datausage/AppDataUsage.java
+++ b/src/com/android/settings/datausage/AppDataUsage.java
@@ -31,6 +31,7 @@
 import android.util.ArraySet;
 import android.util.IconDrawableFactory;
 import android.util.Log;
+import android.util.Range;
 import android.view.View;
 import android.widget.AdapterView;
 
@@ -472,7 +473,9 @@
                         List<NetworkCycleDataForUid> data) {
                     mUsageData = data;
                     mCycle.setOnItemSelectedListener(mCycleListener);
-                    mCycleAdapter.updateCycleList(data);
+                    mCycleAdapter.updateCycleList(data.stream()
+                            .map(cycle -> new Range<>(cycle.getStartTime(), cycle.getEndTime()))
+                            .toList());
                     if (mSelectedCycle > 0L) {
                         final int numCycles = data.size();
                         int position = 0;
diff --git a/src/com/android/settings/datausage/ChartDataUsagePreference.java b/src/com/android/settings/datausage/ChartDataUsagePreference.java
index fa467d2..e5a7307 100644
--- a/src/com/android/settings/datausage/ChartDataUsagePreference.java
+++ b/src/com/android/settings/datausage/ChartDataUsagePreference.java
@@ -26,15 +26,17 @@
 import android.util.DataUnit;
 import android.util.SparseIntArray;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceViewHolder;
 
 import com.android.settings.R;
 import com.android.settings.Utils;
+import com.android.settings.datausage.lib.NetworkCycleChartData;
+import com.android.settings.datausage.lib.NetworkUsageData;
 import com.android.settings.widget.UsageView;
-import com.android.settingslib.net.NetworkCycleChartData;
-import com.android.settingslib.net.NetworkCycleData;
 
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -51,8 +53,8 @@
     private final int mWarningColor;
     private final int mLimitColor;
 
-    private Resources mResources;
-    private NetworkPolicy mPolicy;
+    private final Resources mResources;
+    @Nullable private NetworkPolicy mPolicy;
     private long mStart;
     private long mEnd;
     private NetworkCycleChartData mNetworkCycleChartData;
@@ -67,18 +69,16 @@
     }
 
     @Override
-    public void onBindViewHolder(PreferenceViewHolder holder) {
+    public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
         super.onBindViewHolder(holder);
-        final UsageView chart = (UsageView) holder.findViewById(R.id.data_usage);
-        if (mNetworkCycleChartData == null) {
-            return;
-        }
-
+        final UsageView chart = holder.itemView.requireViewById(R.id.data_usage);
         final int top = getTop();
         chart.clearPaths();
         chart.configureGraph(toInt(mEnd - mStart), top);
-        calcPoints(chart, mNetworkCycleChartData.getUsageBuckets());
-        setupContentDescription(chart, mNetworkCycleChartData.getUsageBuckets());
+        if (mNetworkCycleChartData != null) {
+            calcPoints(chart, mNetworkCycleChartData.getDailyUsage());
+            setupContentDescription(chart, mNetworkCycleChartData.getDailyUsage());
+        }
         chart.setBottomLabels(new CharSequence[] {
                 Utils.formatDateRange(getContext(), mStart, mStart),
                 Utils.formatDateRange(getContext(), mEnd, mEnd),
@@ -88,23 +88,21 @@
     }
 
     public int getTop() {
-        final long totalData = mNetworkCycleChartData.getTotalUsage();
+        final long totalData =
+                mNetworkCycleChartData != null ? mNetworkCycleChartData.getTotal().getUsage() : 0;
         final long policyMax =
             mPolicy != null ? Math.max(mPolicy.limitBytes, mPolicy.warningBytes) : 0;
         return (int) (Math.max(totalData, policyMax) / RESOLUTION);
     }
 
     @VisibleForTesting
-    void calcPoints(UsageView chart, List<NetworkCycleData> usageSummary) {
-        if (usageSummary == null) {
-            return;
-        }
+    void calcPoints(UsageView chart, @NonNull List<NetworkUsageData> usageSummary) {
         final SparseIntArray points = new SparseIntArray();
         points.put(0, 0);
 
         final long now = System.currentTimeMillis();
         long totalData = 0;
-        for (NetworkCycleData data : usageSummary) {
+        for (NetworkUsageData data : usageSummary) {
             final long startTime = data.getStartTime();
             if (startTime > now) {
                 break;
@@ -112,7 +110,7 @@
             final long endTime = data.getEndTime();
 
             // increment by current bucket total
-            totalData += data.getTotalUsage();
+            totalData += data.getUsage();
 
             if (points.size() == 1) {
                 points.put(toInt(startTime - mStart) - 1, -1);
@@ -125,7 +123,8 @@
         }
     }
 
-    private void setupContentDescription(UsageView chart, List<NetworkCycleData> usageSummary) {
+    private void setupContentDescription(
+            UsageView chart, @NonNull List<NetworkUsageData> usageSummary) {
         final Context context = getContext();
         final StringBuilder contentDescription = new StringBuilder();
         final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_MONTH;
@@ -137,7 +136,7 @@
                 .getString(R.string.data_usage_chart_brief_content_description, startDate, endDate);
         contentDescription.append(briefContentDescription);
 
-        if (usageSummary == null || usageSummary.isEmpty()) {
+        if (usageSummary.isEmpty()) {
             final String noDataContentDescription = mResources
                     .getString(R.string.data_usage_chart_no_data_content_description);
             contentDescription.append(noDataContentDescription);
@@ -170,17 +169,17 @@
      * Collect the date of the same percentage, e.g., Aug 2 to Aug 22: 0%; Aug 23: 2%.
      */
     @VisibleForTesting
-    List<DataUsageSummaryNode> getDensedStatsData(List<NetworkCycleData> usageSummary) {
+    List<DataUsageSummaryNode> getDensedStatsData(@NonNull List<NetworkUsageData> usageSummary) {
         final List<DataUsageSummaryNode> dataUsageSummaryNodes = new ArrayList<>();
         final long overallDataUsage = Math.max(1L, usageSummary.stream()
-                .mapToLong(NetworkCycleData::getTotalUsage).sum());
+                .mapToLong(NetworkUsageData::getUsage).sum());
         long cumulatedDataUsage = 0L;
-        int cumulatedDataUsagePercentage = 0;
 
         // Collect List of DataUsageSummaryNode for data usage percentage information.
-        for (NetworkCycleData data : usageSummary) {
-            cumulatedDataUsage += data.getTotalUsage();
-            cumulatedDataUsagePercentage = (int) ((cumulatedDataUsage * 100) / overallDataUsage);
+        for (NetworkUsageData data : usageSummary) {
+            cumulatedDataUsage += data.getUsage();
+            int cumulatedDataUsagePercentage =
+                    (int) ((cumulatedDataUsage * 100) / overallDataUsage);
 
             final DataUsageSummaryNode node = new DataUsageSummaryNode(data.getStartTime(),
                     data.getEndTime(), cumulatedDataUsagePercentage);
@@ -268,8 +267,9 @@
         }
 
         if (policy.warningBytes != NetworkPolicy.WARNING_DISABLED) {
-            chart.setDividerLoc((int) (policy.warningBytes / RESOLUTION));
-            float weight = policy.warningBytes / RESOLUTION / (float) top;
+            int dividerLoc = (int) (policy.warningBytes / RESOLUTION);
+            chart.setDividerLoc(dividerLoc);
+            float weight = dividerLoc / (float) top;
             float above = 1 - weight;
             chart.setSideLabelWeights(above, weight);
             middleVisibility = mWarningColor;
@@ -289,15 +289,21 @@
         return new SpannableStringBuilder().append(label, new ForegroundColorSpan(mLimitColor), 0);
     }
 
-    public void setNetworkPolicy(NetworkPolicy policy) {
+    /** Sets network policy. */
+    public void setNetworkPolicy(@Nullable NetworkPolicy policy) {
         mPolicy = policy;
         notifyChanged();
     }
 
+    /** Sets time. */
+    public void setTime(long start, long end) {
+        mStart = start;
+        mEnd = end;
+        notifyChanged();
+    }
+
     public void setNetworkCycleData(NetworkCycleChartData data) {
         mNetworkCycleChartData = data;
-        mStart = data.getStartTime();
-        mEnd = data.getEndTime();
         notifyChanged();
     }
 }
diff --git a/src/com/android/settings/datausage/ChartDataUsagePreferenceController.kt b/src/com/android/settings/datausage/ChartDataUsagePreferenceController.kt
new file mode 100644
index 0000000..0479be4
--- /dev/null
+++ b/src/com/android/settings/datausage/ChartDataUsagePreferenceController.kt
@@ -0,0 +1,82 @@
+/*
+ * 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.datausage
+
+import android.content.Context
+import android.net.NetworkTemplate
+import androidx.annotation.OpenForTesting
+import androidx.annotation.VisibleForTesting
+import androidx.lifecycle.LifecycleCoroutineScope
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import androidx.preference.PreferenceScreen
+import com.android.settings.core.BasePreferenceController
+import com.android.settings.datausage.lib.INetworkCycleDataRepository
+import com.android.settings.datausage.lib.NetworkCycleDataRepository
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+@OpenForTesting
+open class ChartDataUsagePreferenceController(context: Context, preferenceKey: String) :
+    BasePreferenceController(context, preferenceKey) {
+
+    private lateinit var repository: INetworkCycleDataRepository
+    private lateinit var preference: ChartDataUsagePreference
+    private lateinit var lifecycleScope: LifecycleCoroutineScope
+
+    open fun init(template: NetworkTemplate) {
+        this.repository = NetworkCycleDataRepository(mContext, template)
+    }
+
+    @VisibleForTesting
+    fun init(repository: INetworkCycleDataRepository) {
+        this.repository = repository
+    }
+
+    override fun getAvailabilityStatus() = AVAILABLE
+
+    override fun displayPreference(screen: PreferenceScreen) {
+        super.displayPreference(screen)
+        preference = screen.findPreference(preferenceKey)!!
+    }
+
+    override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+        lifecycleScope = viewLifecycleOwner.lifecycleScope
+    }
+
+    /**
+     * Sets whether billing cycle modifiable.
+     *
+     * Don't bind warning / limit sweeps if not modifiable.
+     */
+    open fun setBillingCycleModifiable(isModifiable: Boolean) {
+        preference.setNetworkPolicy(
+            if (isModifiable) repository.getPolicy() else null
+        )
+    }
+
+    fun update(startTime: Long, endTime: Long) {
+        preference.setTime(startTime, endTime)
+        lifecycleScope.launch {
+            val chartData = withContext(Dispatchers.Default) {
+                repository.querySummary(startTime, endTime)
+            }
+            preference.setNetworkCycleData(chartData)
+        }
+    }
+}
diff --git a/src/com/android/settings/datausage/CycleAdapter.java b/src/com/android/settings/datausage/CycleAdapter.java
index 90a2035..7cff05e 100644
--- a/src/com/android/settings/datausage/CycleAdapter.java
+++ b/src/com/android/settings/datausage/CycleAdapter.java
@@ -14,9 +14,9 @@
 package com.android.settings.datausage;
 
 import android.content.Context;
+import android.util.Range;
 
 import com.android.settings.Utils;
-import com.android.settingslib.net.NetworkCycleData;
 import com.android.settingslib.widget.SettingsSpinnerAdapter;
 
 import java.util.List;
@@ -62,15 +62,15 @@
      * Rebuild list based on network data. Always selects the newest item,
      * updating the inspection range on chartData.
      */
-    public void updateCycleList(List<? extends NetworkCycleData> cycleData) {
+    public void updateCycleList(List<Range<Long>> cycleData) {
         // stash away currently selected cycle to try restoring below
         final CycleAdapter.CycleItem previousItem = (CycleAdapter.CycleItem)
                 mSpinner.getSelectedItem();
         clear();
 
         final Context context = getContext();
-        for (NetworkCycleData data : cycleData) {
-            add(new CycleAdapter.CycleItem(context, data.getStartTime(), data.getEndTime()));
+        for (Range<Long> cycle : cycleData) {
+            add(new CycleAdapter.CycleItem(context, cycle.getLower(), cycle.getUpper()));
         }
 
         // force pick the current cycle (first item)
diff --git a/src/com/android/settings/datausage/DataUsageList.java b/src/com/android/settings/datausage/DataUsageList.java
deleted file mode 100644
index e7345ab..0000000
--- a/src/com/android/settings/datausage/DataUsageList.java
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Copyright (C) 2018 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.datausage;
-
-import android.app.Activity;
-import android.app.settings.SettingsEnums;
-import android.content.Context;
-import android.content.Intent;
-import android.net.NetworkPolicy;
-import android.net.NetworkTemplate;
-import android.os.Bundle;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.telephony.SubscriptionManager;
-import android.util.EventLog;
-import android.util.Log;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-import androidx.lifecycle.Lifecycle;
-import androidx.loader.app.LoaderManager.LoaderCallbacks;
-import androidx.loader.content.Loader;
-import androidx.preference.Preference;
-
-import com.android.settings.R;
-import com.android.settings.datausage.lib.BillingCycleRepository;
-import com.android.settings.network.MobileDataEnabledListener;
-import com.android.settings.network.MobileNetworkRepository;
-import com.android.settings.widget.LoadingViewController;
-import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
-import com.android.settingslib.net.NetworkCycleChartData;
-import com.android.settingslib.net.NetworkCycleChartDataLoader;
-import com.android.settingslib.utils.ThreadUtils;
-
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-
-import kotlin.Unit;
-
-/**
- * Panel showing data usage history across various networks, including options
- * to inspect based on usage cycle and control through {@link NetworkPolicy}.
- */
-public class DataUsageList extends DataUsageBaseFragment
-        implements MobileDataEnabledListener.Client {
-
-    static final String EXTRA_SUB_ID = "sub_id";
-    static final String EXTRA_NETWORK_TEMPLATE = "network_template";
-
-    private static final String TAG = "DataUsageList";
-    private static final boolean LOGD = false;
-
-    private static final String KEY_USAGE_AMOUNT = "usage_amount";
-    private static final String KEY_CHART_DATA = "chart_data";
-    private static final String KEY_TEMPLATE = "template";
-    private static final String KEY_APP = "app";
-
-    @VisibleForTesting
-    static final int LOADER_CHART_DATA = 2;
-
-    @VisibleForTesting
-    MobileDataEnabledListener mDataStateListener;
-
-    @VisibleForTesting
-    NetworkTemplate mTemplate;
-    @VisibleForTesting
-    int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-    @VisibleForTesting
-    LoadingViewController mLoadingViewController;
-
-    private ChartDataUsagePreference mChart;
-
-    @Nullable
-    private List<NetworkCycleChartData> mCycleData;
-
-    // Spinner will keep the selected cycle even after paused, this only keeps the displayed cycle,
-    // which need be cleared when resumed.
-    private CycleAdapter.CycleItem mLastDisplayedCycle;
-    private Preference mUsageAmount;
-    private MobileNetworkRepository mMobileNetworkRepository;
-    private SubscriptionInfoEntity mSubscriptionInfoEntity;
-    private DataUsageListAppsController mDataUsageListAppsController;
-    private BillingCycleRepository mBillingCycleRepository;
-    @VisibleForTesting
-    DataUsageListHeaderController mDataUsageListHeaderController;
-
-    private boolean mIsBillingCycleModifiable = false;
-
-    @Override
-    public int getMetricsCategory() {
-        return SettingsEnums.DATA_USAGE_LIST;
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        if (isGuestUser(getContext())) {
-            Log.e(TAG, "This setting isn't available for guest user");
-            EventLog.writeEvent(0x534e4554, "262741858", -1 /* UID */, "Guest user");
-            finish();
-            return;
-        }
-
-        final Activity activity = getActivity();
-        mBillingCycleRepository = createBillingCycleRepository();
-        if (!mBillingCycleRepository.isBandwidthControlEnabled()) {
-            Log.w(TAG, "No bandwidth control; leaving");
-            activity.finish();
-            return;
-        }
-
-        mUsageAmount = findPreference(KEY_USAGE_AMOUNT);
-        mChart = findPreference(KEY_CHART_DATA);
-
-        processArgument();
-        if (mTemplate == null) {
-            Log.e(TAG, "No template; leaving");
-            finish();
-            return;
-        }
-        updateSubscriptionInfoEntity();
-        mDataStateListener = new MobileDataEnabledListener(activity, this);
-        mDataUsageListAppsController = use(DataUsageListAppsController.class);
-        mDataUsageListAppsController.init(mTemplate);
-    }
-
-    @VisibleForTesting
-    @NonNull
-    BillingCycleRepository createBillingCycleRepository() {
-        return new BillingCycleRepository(requireContext());
-    }
-
-    @Override
-    public void onViewCreated(@NonNull View v, Bundle savedInstanceState) {
-        super.onViewCreated(v, savedInstanceState);
-
-        mDataUsageListHeaderController = new DataUsageListHeaderController(
-                setPinnedHeaderView(R.layout.apps_filter_spinner),
-                mTemplate,
-                getMetricsCategory(),
-                (cycle, position) -> {
-                    updateSelectedCycle(cycle, position);
-                    return Unit.INSTANCE;
-                }
-        );
-
-        mLoadingViewController = new LoadingViewController(
-                getView().findViewById(R.id.loading_container), getListView());
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        mLoadingViewController.showLoadingViewDelayed();
-        mDataStateListener.start(mSubId);
-        mLastDisplayedCycle = null;
-        updatePolicy();
-
-        // kick off loader for network history
-        // TODO: consider chaining two loaders together instead of reloading
-        // network history when showing app detail.
-        getLoaderManager().restartLoader(LOADER_CHART_DATA,
-                buildArgs(mTemplate), mNetworkCycleDataCallbacks);
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        mDataStateListener.stop();
-
-        getLoaderManager().destroyLoader(LOADER_CHART_DATA);
-    }
-
-    @Override
-    protected int getPreferenceScreenResId() {
-        return R.xml.data_usage_list;
-    }
-
-    @Override
-    protected String getLogTag() {
-        return TAG;
-    }
-
-    void processArgument() {
-        final Bundle args = getArguments();
-        if (args != null) {
-            mSubId = args.getInt(EXTRA_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
-            mTemplate = args.getParcelable(EXTRA_NETWORK_TEMPLATE);
-        }
-        if (mTemplate == null && mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
-            final Intent intent = getIntent();
-            mSubId = intent.getIntExtra(Settings.EXTRA_SUB_ID,
-                    SubscriptionManager.INVALID_SUBSCRIPTION_ID);
-            mTemplate = intent.getParcelableExtra(Settings.EXTRA_NETWORK_TEMPLATE);
-
-            if (mTemplate == null) {
-                Optional<NetworkTemplate> mobileNetworkTemplateFromSim =
-                        DataUsageUtils.getMobileNetworkTemplateFromSubId(getContext(), getIntent());
-                if (mobileNetworkTemplateFromSim.isPresent()) {
-                    mTemplate = mobileNetworkTemplateFromSim.get();
-                }
-            }
-        }
-    }
-
-    @VisibleForTesting
-    void updateSubscriptionInfoEntity() {
-        mMobileNetworkRepository = MobileNetworkRepository.getInstance(getContext());
-        ThreadUtils.postOnBackgroundThread(() -> {
-            mSubscriptionInfoEntity = mMobileNetworkRepository.getSubInfoById(
-                    String.valueOf(mSubId));
-        });
-    }
-
-    /**
-     * Implementation of {@code MobileDataEnabledListener.Client}
-     */
-    public void onMobileDataEnabledChange() {
-        updatePolicy();
-    }
-
-    private Bundle buildArgs(NetworkTemplate template) {
-        final Bundle args = new Bundle();
-        args.putParcelable(KEY_TEMPLATE, template);
-        args.putParcelable(KEY_APP, null);
-        return args;
-    }
-
-    /**
-     * Update chart sweeps and cycle list to reflect {@link NetworkPolicy} for
-     * current {@link #mTemplate}.
-     */
-    @VisibleForTesting
-    void updatePolicy() {
-        mIsBillingCycleModifiable = isBillingCycleModifiable();
-        if (mIsBillingCycleModifiable) {
-            mChart.setNetworkPolicy(services.mPolicyEditor.getPolicy(mTemplate));
-        } else {
-            mChart.setNetworkPolicy(null);  // don't bind warning / limit sweeps
-        }
-        updateConfigButtonVisibility();
-    }
-
-    @VisibleForTesting
-    boolean isBillingCycleModifiable() {
-        return mBillingCycleRepository.isModifiable(mSubId)
-                && SubscriptionManager.from(requireContext())
-                .getActiveSubscriptionInfo(mSubId) != null;
-    }
-
-    private void updateConfigButtonVisibility() {
-        mDataUsageListHeaderController.setConfigButtonVisible(
-                mIsBillingCycleModifiable && mCycleData != null);
-    }
-
-    /**
-     * Updates the chart and detail data when initial loaded or selected cycle changed.
-     */
-    private void updateSelectedCycle(CycleAdapter.CycleItem cycle, int position) {
-        // Avoid from updating UI after #onStop.
-        if (!getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
-            return;
-        }
-
-        // Avoid from updating UI when async query still on-going.
-        // This could happen when a request from #onMobileDataEnabledChange.
-        if (mCycleData == null) {
-            return;
-        }
-
-        if (Objects.equals(cycle, mLastDisplayedCycle)) {
-            // Avoid duplicate update to avoid page flash.
-            return;
-        }
-        mLastDisplayedCycle = cycle;
-
-        if (LOGD) {
-            Log.d(TAG, "showing cycle " + cycle + ", [start=" + cycle.start + ", end="
-                    + cycle.end + "]");
-        }
-
-        // update chart to show selected cycle, and update detail data
-        // to match updated sweep bounds.
-        NetworkCycleChartData cycleChartData = mCycleData.get(position);
-        mChart.setNetworkCycleData(cycleChartData);
-
-        updateDetailData(cycleChartData);
-    }
-
-    /**
-     * Update details based on {@link #mChart} inspection range depending on
-     * current mode. Updates {@link #mAdapter} with sorted list
-     * of applications data usage.
-     */
-    private void updateDetailData(NetworkCycleChartData cycleChartData) {
-        if (LOGD) Log.d(TAG, "updateDetailData()");
-
-        // kick off loader for detailed stats
-        mDataUsageListAppsController.update(
-                mSubscriptionInfoEntity == null ? null : mSubscriptionInfoEntity.carrierId,
-                cycleChartData.getStartTime(),
-                cycleChartData.getEndTime()
-        );
-
-        final long totalBytes = cycleChartData.getTotalUsage();
-        final CharSequence totalPhrase = DataUsageUtils.formatDataUsage(getActivity(), totalBytes);
-        mUsageAmount.setTitle(getString(R.string.data_used_template, totalPhrase));
-    }
-
-    @VisibleForTesting
-    final LoaderCallbacks<List<NetworkCycleChartData>> mNetworkCycleDataCallbacks =
-            new LoaderCallbacks<>() {
-                @Override
-                @NonNull
-                public Loader<List<NetworkCycleChartData>> onCreateLoader(int id, Bundle args) {
-                    return NetworkCycleChartDataLoader.builder(getContext())
-                            .setNetworkTemplate(mTemplate)
-                            .build();
-                }
-
-                @Override
-                public void onLoadFinished(@NonNull Loader<List<NetworkCycleChartData>> loader,
-                        List<NetworkCycleChartData> data) {
-                    mLoadingViewController.showContent(false /* animate */);
-                    mCycleData = data;
-                    mDataUsageListHeaderController.updateCycleData(mCycleData);
-                    updateConfigButtonVisibility();
-                    mDataUsageListAppsController.setCycleData(mCycleData);
-                }
-
-                @Override
-                public void onLoaderReset(@NonNull Loader<List<NetworkCycleChartData>> loader) {
-                    mCycleData = null;
-                }
-            };
-
-    private static boolean isGuestUser(Context context) {
-        if (context == null) return false;
-        final UserManager userManager = context.getSystemService(UserManager.class);
-        if (userManager == null) return false;
-        return userManager.isGuestUser();
-    }
-}
diff --git a/src/com/android/settings/datausage/DataUsageList.kt b/src/com/android/settings/datausage/DataUsageList.kt
new file mode 100644
index 0000000..9ac7161
--- /dev/null
+++ b/src/com/android/settings/datausage/DataUsageList.kt
@@ -0,0 +1,229 @@
+/*
+ * 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.datausage
+
+import android.app.settings.SettingsEnums
+import android.net.NetworkPolicy
+import android.net.NetworkTemplate
+import android.os.Bundle
+import android.provider.Settings
+import android.telephony.SubscriptionManager
+import android.util.EventLog
+import android.util.Log
+import android.view.View
+import androidx.annotation.OpenForTesting
+import androidx.annotation.VisibleForTesting
+import androidx.preference.Preference
+import com.android.settings.R
+import com.android.settings.datausage.lib.BillingCycleRepository
+import com.android.settings.datausage.lib.NetworkUsageData
+import com.android.settings.network.MobileDataEnabledListener
+import com.android.settings.network.MobileNetworkRepository
+import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity
+import com.android.settingslib.spaprivileged.framework.common.userManager
+import com.android.settingslib.utils.ThreadUtils
+import kotlin.jvm.optionals.getOrNull
+
+/**
+ * Panel showing data usage history across various networks, including options
+ * to inspect based on usage cycle and control through [NetworkPolicy].
+ */
+@OpenForTesting
+open class DataUsageList : DataUsageBaseFragment(), MobileDataEnabledListener.Client {
+    @VisibleForTesting
+    lateinit var dataStateListener: MobileDataEnabledListener
+
+    @JvmField
+    @VisibleForTesting
+    var template: NetworkTemplate? = null
+
+    @JvmField
+    @VisibleForTesting
+    var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID
+
+    // Spinner will keep the selected cycle even after paused, this only keeps the displayed cycle,
+    // which need be cleared when resumed.
+    private var lastDisplayedUsageData: NetworkUsageData? = null
+    private lateinit var usageAmount: Preference
+    private var subscriptionInfoEntity: SubscriptionInfoEntity? = null
+    private lateinit var dataUsageListAppsController: DataUsageListAppsController
+    private lateinit var chartDataUsagePreferenceController: ChartDataUsagePreferenceController
+    private lateinit var billingCycleRepository: BillingCycleRepository
+
+    @VisibleForTesting
+    var dataUsageListHeaderController: DataUsageListHeaderController? = null
+
+    override fun getMetricsCategory() = SettingsEnums.DATA_USAGE_LIST
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        if (requireContext().userManager.isGuestUser) {
+            Log.e(TAG, "This setting isn't available for guest user")
+            EventLog.writeEvent(0x534e4554, "262741858", -1 /* UID */, "Guest user")
+            finish()
+            return
+        }
+        billingCycleRepository = createBillingCycleRepository();
+        if (!billingCycleRepository.isBandwidthControlEnabled()) {
+            Log.w(TAG, "No bandwidth control; leaving")
+            finish()
+            return
+        }
+        usageAmount = findPreference(KEY_USAGE_AMOUNT)!!
+        processArgument()
+        val template = template
+        if (template == null) {
+            Log.e(TAG, "No template; leaving")
+            finish()
+            return
+        }
+        updateSubscriptionInfoEntity()
+        dataStateListener = MobileDataEnabledListener(activity, this)
+        dataUsageListAppsController = use(DataUsageListAppsController::class.java).apply {
+            init(template)
+        }
+        chartDataUsagePreferenceController = use(ChartDataUsagePreferenceController::class.java)
+        chartDataUsagePreferenceController.init(template)
+    }
+
+    @VisibleForTesting
+    open fun createBillingCycleRepository() = BillingCycleRepository(requireContext())
+
+    override fun onViewCreated(v: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(v, savedInstanceState)
+
+        val template = template ?: return
+        dataUsageListHeaderController = DataUsageListHeaderController(
+            setPinnedHeaderView(R.layout.apps_filter_spinner),
+            template,
+            metricsCategory,
+            viewLifecycleOwner,
+            ::onCyclesLoad,
+            ::updateSelectedCycle,
+        )
+    }
+
+    override fun onResume() {
+        super.onResume()
+        dataStateListener.start(subId)
+        lastDisplayedUsageData = null
+        updatePolicy()
+    }
+
+    override fun onPause() {
+        super.onPause()
+        dataStateListener.stop()
+    }
+
+    override fun getPreferenceScreenResId() = R.xml.data_usage_list
+
+    override fun getLogTag() = TAG
+
+    fun processArgument() {
+        arguments?.let {
+            subId = it.getInt(EXTRA_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+            template = it.getParcelable(EXTRA_NETWORK_TEMPLATE, NetworkTemplate::class.java)
+        }
+        if (template == null && subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            subId = intent.getIntExtra(
+                Settings.EXTRA_SUB_ID,
+                SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+            )
+            template = intent.getParcelableExtra(
+                Settings.EXTRA_NETWORK_TEMPLATE,
+                NetworkTemplate::class.java,
+            ) ?: DataUsageUtils.getMobileNetworkTemplateFromSubId(context, intent).getOrNull()
+        }
+    }
+
+    @VisibleForTesting
+    open fun updateSubscriptionInfoEntity() {
+        ThreadUtils.postOnBackgroundThread {
+            subscriptionInfoEntity =
+                MobileNetworkRepository.getInstance(context).getSubInfoById(subId.toString())
+        }
+    }
+
+    /**
+     * Implementation of `MobileDataEnabledListener.Client`
+     */
+    override fun onMobileDataEnabledChange() {
+        updatePolicy()
+    }
+
+    /** Update chart sweeps and cycle list to reflect [NetworkPolicy] for current [template]. */
+    @VisibleForTesting
+    fun updatePolicy() {
+        val isBillingCycleModifiable = isBillingCycleModifiable()
+        dataUsageListHeaderController?.setConfigButtonVisible(isBillingCycleModifiable)
+        chartDataUsagePreferenceController.setBillingCycleModifiable(isBillingCycleModifiable)
+    }
+
+    @VisibleForTesting
+    open fun isBillingCycleModifiable(): Boolean {
+        return (billingCycleRepository.isModifiable(subId) &&
+            requireContext().getSystemService(SubscriptionManager::class.java)!!
+                .getActiveSubscriptionInfo(subId) != null)
+    }
+
+    private fun onCyclesLoad(networkUsageData: List<NetworkUsageData>) {
+        dataUsageListAppsController.updateCycles(networkUsageData)
+    }
+
+    /**
+     * Updates the chart and detail data when initial loaded or selected cycle changed.
+     */
+    private fun updateSelectedCycle(usageData: NetworkUsageData) {
+        if (usageData == lastDisplayedUsageData) {
+            // Avoid duplicate update to avoid page flash.
+            return
+        }
+        lastDisplayedUsageData = usageData
+        Log.d(TAG, "showing cycle $usageData")
+
+        val totalPhrase = DataUsageUtils.formatDataUsage(requireContext(), usageData.usage)
+        usageAmount.title = getString(R.string.data_used_template, totalPhrase)
+
+        updateChart(usageData)
+        updateApps(usageData)
+    }
+
+    /** Updates chart to show selected cycle. */
+    private fun updateChart(usageData: NetworkUsageData) {
+        chartDataUsagePreferenceController.update(
+            startTime = usageData.startTime,
+            endTime = usageData.endTime,
+        )
+    }
+
+    /** Updates applications data usage. */
+    private fun updateApps(usageData: NetworkUsageData) {
+        dataUsageListAppsController.update(
+            carrierId = subscriptionInfoEntity?.carrierId,
+            startTime = usageData.startTime,
+            endTime = usageData.endTime,
+        )
+    }
+
+    companion object {
+        const val EXTRA_SUB_ID = "sub_id"
+        const val EXTRA_NETWORK_TEMPLATE = "network_template"
+
+        private const val TAG = "DataUsageList"
+        private const val KEY_USAGE_AMOUNT = "usage_amount"
+    }
+}
diff --git a/src/com/android/settings/datausage/DataUsageListAppsController.kt b/src/com/android/settings/datausage/DataUsageListAppsController.kt
index c324407..93623f4 100644
--- a/src/com/android/settings/datausage/DataUsageListAppsController.kt
+++ b/src/com/android/settings/datausage/DataUsageListAppsController.kt
@@ -31,8 +31,8 @@
 import com.android.settings.core.BasePreferenceController
 import com.android.settings.core.SubSettingLauncher
 import com.android.settings.datausage.lib.AppDataUsageRepository
+import com.android.settings.datausage.lib.NetworkUsageData
 import com.android.settingslib.AppItem
-import com.android.settingslib.net.NetworkCycleChartData
 import com.android.settingslib.net.UidDetailProvider
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
@@ -48,7 +48,7 @@
     private lateinit var preference: PreferenceGroup
     private lateinit var lifecycleScope: LifecycleCoroutineScope
 
-    private var cycleData: List<NetworkCycleChartData>? = null
+    private var cycleData: List<NetworkUsageData>? = null
 
     open fun init(template: NetworkTemplate) {
         this.template = template
@@ -70,7 +70,7 @@
         lifecycleScope = viewLifecycleOwner.lifecycleScope
     }
 
-    fun setCycleData(cycleData: List<NetworkCycleChartData>?) {
+    fun updateCycles(cycleData: List<NetworkUsageData>) {
         this.cycleData = cycleData
     }
 
diff --git a/src/com/android/settings/datausage/DataUsageListHeaderController.kt b/src/com/android/settings/datausage/DataUsageListHeaderController.kt
index e295a4c..58fc3b5 100644
--- a/src/com/android/settings/datausage/DataUsageListHeaderController.kt
+++ b/src/com/android/settings/datausage/DataUsageListHeaderController.kt
@@ -18,25 +18,39 @@
 
 import android.net.NetworkTemplate
 import android.os.Bundle
+import android.util.Range
 import android.view.View
 import android.view.accessibility.AccessibilityEvent
 import android.widget.AdapterView
 import android.widget.Spinner
 import androidx.annotation.OpenForTesting
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
 import com.android.settings.R
 import com.android.settings.core.SubSettingLauncher
-import com.android.settings.datausage.CycleAdapter.CycleItem
 import com.android.settings.datausage.CycleAdapter.SpinnerInterface
-import com.android.settingslib.net.NetworkCycleChartData
+import com.android.settings.datausage.lib.INetworkCycleDataRepository
+import com.android.settings.datausage.lib.NetworkCycleDataRepository
+import com.android.settings.datausage.lib.NetworkUsageData
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
 
 @OpenForTesting
 open class DataUsageListHeaderController(
     header: View,
     template: NetworkTemplate,
     sourceMetricsCategory: Int,
-    private val onItemSelected: (cycleItem: CycleItem, position: Int) -> Unit,
+    viewLifecycleOwner: LifecycleOwner,
+    private val onCyclesLoad: (usageDataList: List<NetworkUsageData>) -> Unit,
+    private val onItemSelected: (usageData: NetworkUsageData) -> Unit,
+    private val repository: INetworkCycleDataRepository =
+        NetworkCycleDataRepository(header.context, template),
 ) {
     private val context = header.context
+
     private val configureButton: View = header.requireViewById(R.id.filter_settings)
     private val cycleSpinner: Spinner = header.requireViewById(R.id.filter_spinner)
     private val cycleAdapter = CycleAdapter(context, object : SpinnerInterface {
@@ -50,13 +64,12 @@
             cycleSpinner.setSelection(position)
         }
     })
+    private var cycles: List<NetworkUsageData> = emptyList()
 
     private val cycleListener = object : AdapterView.OnItemSelectedListener {
         override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
             if (0 <= position && position < cycleAdapter.count) {
-                cycleAdapter.getItem(position)?.let { cycleItem ->
-                    onItemSelected(cycleItem, position)
-                }
+                cycles.getOrNull(position)?.let(onItemSelected)
             }
         }
 
@@ -80,24 +93,32 @@
         cycleSpinner.visibility = View.GONE
         cycleSpinner.accessibilityDelegate = object : View.AccessibilityDelegate() {
             override fun sendAccessibilityEvent(host: View, eventType: Int) {
-                if (eventType == AccessibilityEvent.TYPE_VIEW_SELECTED) {
-                    // Ignore TYPE_VIEW_SELECTED or TalkBack will speak for it at onResume.
-                    return
-                }
+                // Ignore TYPE_VIEW_SELECTED or TalkBack will speak for it at onResume.
+                if (eventType == AccessibilityEvent.TYPE_VIEW_SELECTED) return
                 super.sendAccessibilityEvent(host, eventType)
             }
         }
+
+        viewLifecycleOwner.lifecycleScope.launch {
+            viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
+                cycles = withContext(Dispatchers.Default) {
+                    repository.loadCycles()
+                }
+                updateCycleData()
+            }
+        }
     }
 
     open fun setConfigButtonVisible(visible: Boolean) {
         configureButton.visibility = if (visible) View.VISIBLE else View.GONE
     }
 
-    open fun updateCycleData(cycleData: List<NetworkCycleChartData>) {
+    private fun updateCycleData() {
         cycleSpinner.onItemSelectedListener = cycleListener
         // calculate policy cycles based on available data
         // generate cycle list based on policy and available history
-        cycleAdapter.updateCycleList(cycleData)
+        cycleAdapter.updateCycleList(cycles.map { Range(it.startTime, it.endTime) })
         cycleSpinner.visibility = View.VISIBLE
+        onCyclesLoad(cycles)
     }
 }
diff --git a/src/com/android/settings/datausage/lib/NetworkCycleChartData.kt b/src/com/android/settings/datausage/lib/NetworkCycleChartData.kt
new file mode 100644
index 0000000..fd3c504
--- /dev/null
+++ b/src/com/android/settings/datausage/lib/NetworkCycleChartData.kt
@@ -0,0 +1,31 @@
+/*
+ * 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.datausage.lib
+
+import kotlin.time.Duration.Companion.days
+
+/**
+ * Usage data in a billing cycle with daily data for plotting the usage chart.
+ */
+data class NetworkCycleChartData(
+    val total: NetworkUsageData,
+    val dailyUsage: List<NetworkUsageData>,
+) {
+    companion object {
+        val BUCKET_DURATION = 1.days
+    }
+}
diff --git a/src/com/android/settings/datausage/lib/NetworkCycleDataRepository.kt b/src/com/android/settings/datausage/lib/NetworkCycleDataRepository.kt
new file mode 100644
index 0000000..f10d506
--- /dev/null
+++ b/src/com/android/settings/datausage/lib/NetworkCycleDataRepository.kt
@@ -0,0 +1,154 @@
+/*
+ * 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.datausage.lib
+
+import android.app.usage.NetworkStats
+import android.app.usage.NetworkStatsManager
+import android.content.Context
+import android.net.NetworkPolicy
+import android.net.NetworkPolicyManager
+import android.net.NetworkTemplate
+import android.text.format.DateUtils
+import android.util.Log
+import android.util.Range
+import androidx.annotation.VisibleForTesting
+import com.android.settingslib.NetworkPolicyEditor
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
+import kotlinx.coroutines.coroutineScope
+
+interface INetworkCycleDataRepository {
+    suspend fun loadCycles(): List<NetworkUsageData>
+    fun getPolicy(): NetworkPolicy?
+    suspend fun querySummary(startTime: Long, endTime: Long): NetworkCycleChartData?
+}
+
+class NetworkCycleDataRepository(
+    context: Context,
+    private val networkTemplate: NetworkTemplate,
+) : INetworkCycleDataRepository {
+    private val networkStatsManager = context.getSystemService(NetworkStatsManager::class.java)!!
+
+    private val policyManager = context.getSystemService(NetworkPolicyManager::class.java)!!
+
+    override suspend fun loadCycles(): List<NetworkUsageData> =
+        getCycles().queryUsage().filter { it.usage > 0 }
+
+    private fun getCycles(): List<Range<Long>> {
+        val policy = getPolicy() ?: return queryCyclesAsFourWeeks()
+        return policy.cycleIterator().asSequence().map {
+            Range(it.lower.toInstant().toEpochMilli(), it.upper.toInstant().toEpochMilli())
+        }.toList()
+    }
+
+    private fun queryCyclesAsFourWeeks(): List<Range<Long>> {
+        val timeRange = getTimeRange()
+        return reverseBucketRange(
+            startTime = timeRange.lower,
+            endTime = timeRange.upper,
+            bucketSize = DateUtils.WEEK_IN_MILLIS * 4,
+        )
+    }
+
+    @VisibleForTesting
+    fun getTimeRange(): Range<Long> = getTimeRangeOf(
+        networkStatsManager.queryDetailsForDevice(networkTemplate, Long.MIN_VALUE, Long.MAX_VALUE)
+    )
+
+    private fun getTimeRangeOf(stats: NetworkStats): Range<Long> {
+        var start = Long.MAX_VALUE
+        var end = Long.MIN_VALUE
+        val bucket = NetworkStats.Bucket()
+        while (stats.getNextBucket(bucket)) {
+            start = start.coerceAtMost(bucket.startTimeStamp)
+            end = end.coerceAtLeast(bucket.endTimeStamp)
+        }
+        return Range(start, end)
+    }
+
+    override fun getPolicy(): NetworkPolicy? =
+        with(NetworkPolicyEditor(policyManager)) {
+            read()
+            getPolicy(networkTemplate)
+        }
+
+    override suspend fun querySummary(startTime: Long, endTime: Long): NetworkCycleChartData? {
+        val usage = getUsage(startTime, endTime)
+        if (usage > 0L) {
+            return NetworkCycleChartData(
+                total = NetworkUsageData(startTime, endTime, usage),
+                dailyUsage = bucketRange(
+                    startTime = startTime,
+                    endTime = endTime,
+                    bucketSize = NetworkCycleChartData.BUCKET_DURATION.inWholeMilliseconds,
+                ).queryUsage(),
+            )
+        }
+        return null
+    }
+
+    private suspend fun List<Range<Long>>.queryUsage(): List<NetworkUsageData> = coroutineScope {
+        map { range ->
+            async {
+                NetworkUsageData(
+                    startTime = range.lower,
+                    endTime = range.upper,
+                    usage = getUsage(range.lower, range.upper),
+                )
+            }
+        }.awaitAll()
+    }
+
+    private fun bucketRange(startTime: Long, endTime: Long, bucketSize: Long): List<Range<Long>> {
+        val buckets = mutableListOf<Range<Long>>()
+        var currentStart = startTime
+        while (currentStart < endTime) {
+            val bucketEnd = currentStart + bucketSize
+            buckets += Range(currentStart, bucketEnd)
+            currentStart = bucketEnd
+        }
+        return buckets
+    }
+
+    private fun reverseBucketRange(
+        startTime: Long,
+        endTime: Long,
+        bucketSize: Long,
+    ): List<Range<Long>> {
+        val buckets = mutableListOf<Range<Long>>()
+        var currentEnd = endTime
+        while (currentEnd > startTime) {
+            val bucketStart = currentEnd - bucketSize
+            buckets += Range(bucketStart, currentEnd)
+            currentEnd = bucketStart
+        }
+        return buckets
+    }
+
+    private fun getUsage(start: Long, end: Long): Long = try {
+        networkStatsManager.querySummaryForDevice(networkTemplate, start, end).let {
+            it.rxBytes + it.txBytes
+        }
+    } catch (e: Exception) {
+        Log.e(TAG, "Exception querying network detail.", e)
+        0
+    }
+
+    companion object {
+        private const val TAG = "NetworkCycleDataRepository"
+    }
+}
diff --git a/src/com/android/settings/datausage/lib/NetworkUsageData.kt b/src/com/android/settings/datausage/lib/NetworkUsageData.kt
new file mode 100644
index 0000000..fc5db2b
--- /dev/null
+++ b/src/com/android/settings/datausage/lib/NetworkUsageData.kt
@@ -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.
+ */
+
+package com.android.settings.datausage.lib
+
+/**
+ * Base data structure representing usage data in a period.
+ */
+data class NetworkUsageData(
+    val startTime: Long,
+    val endTime: Long,
+    val usage: Long,
+)
diff --git a/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverController.java b/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverController.java
index b3af95e..95cf64c 100644
--- a/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverController.java
+++ b/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverController.java
@@ -57,6 +57,10 @@
     @VisibleForTesting
     static final String PROPERTY_PERSISTENT_GRAPHICS_EGL = "persist.graphics.egl";
 
+    @VisibleForTesting
+    static final String PROPERTY_DEBUG_ANGLE_DEVELOPER_OPTION =
+            "debug.graphics.angle.developeroption.enable";
+
     @VisibleForTesting static final String ANGLE_DRIVER_SUFFIX = "angle";
 
     @VisibleForTesting
@@ -72,6 +76,11 @@
                 public void set(String key, String val) {
                     SystemProperties.set(key, val);
                 }
+
+                @Override
+                public boolean getBoolean(String key, boolean def) {
+                    return SystemProperties.getBoolean(key, def);
+                }
             };
         }
     }
@@ -81,6 +90,13 @@
         this(context, fragment, new Injector());
     }
 
+    // Return true if the ANGLE developer option entry point is enabled.
+    // This can be enabled by calling:
+    //     `adb shell setprop debug.graphics.angle.developeroption.enable true`
+    private boolean isAngleDeveloperOptionEnabled() {
+        return mSystemProperties.getBoolean(PROPERTY_DEBUG_ANGLE_DEVELOPER_OPTION, false);
+    }
+
     private boolean isAngleSupported() {
         return TextUtils.equals(
                         mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true");
@@ -96,6 +112,10 @@
         // Exception is when user chooses to reboot now, the switch should keep its current value
         // and persist its' state over reboot.
         mShouldToggleSwitchBackOnRebootDialogDismiss = true;
+        final String persistGraphicsEglValue =
+                mSystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL, "");
+        Log.v(TAG, "Value of " + PROPERTY_PERSISTENT_GRAPHICS_EGL + " is: "
+                + persistGraphicsEglValue);
     }
 
     @Override
@@ -149,6 +169,12 @@
             mPreference.setEnabled(false);
             ((SwitchPreference) mPreference).setChecked(false);
         }
+
+        // Regardless of whether ANGLE is enabled, disable the developer option UI
+        // as long as UI is not enabled via debug property.
+        if (!isAngleDeveloperOptionEnabled()) {
+            mPreference.setEnabled(false);
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/development/graphicsdriver/GraphicsDriverSystemPropertiesWrapper.java b/src/com/android/settings/development/graphicsdriver/GraphicsDriverSystemPropertiesWrapper.java
index 549cd81..9684282 100644
--- a/src/com/android/settings/development/graphicsdriver/GraphicsDriverSystemPropertiesWrapper.java
+++ b/src/com/android/settings/development/graphicsdriver/GraphicsDriverSystemPropertiesWrapper.java
@@ -41,4 +41,13 @@
      * SELinux. libc will log the underlying reason.
      */
     void set(@NonNull String key, @Nullable String val);
+
+    /**
+     * Get the boolean value for the given {@code key}.
+     *
+     * @param key the key to lookup
+     * @param def the default value in case the property is not set or empty
+     * @return if the {@code key} isn't found, return {@code def}.
+     */
+    boolean getBoolean(@NonNull String key, @NonNull boolean def);
 }
diff --git a/src/com/android/settings/display/AutoRotatePreferenceController.java b/src/com/android/settings/display/AutoRotatePreferenceController.java
index f16cbfb..ec2592d 100644
--- a/src/com/android/settings/display/AutoRotatePreferenceController.java
+++ b/src/com/android/settings/display/AutoRotatePreferenceController.java
@@ -103,7 +103,8 @@
         final boolean isLocked = !isChecked;
         mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_ROTATION_LOCK,
                 isLocked);
-        RotationPolicy.setRotationLock(mContext, isLocked);
+        RotationPolicy.setRotationLock(mContext, isLocked,
+                /* caller= */ "AutoRotatePreferenceController#setChecked");
         return true;
     }
 }
diff --git a/src/com/android/settings/display/AutoRotateSwitchBarController.java b/src/com/android/settings/display/AutoRotateSwitchBarController.java
index 93420b0..e6fc2e3 100644
--- a/src/com/android/settings/display/AutoRotateSwitchBarController.java
+++ b/src/com/android/settings/display/AutoRotateSwitchBarController.java
@@ -82,7 +82,8 @@
         final boolean isLocked = !isChecked;
         mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_ROTATE_ROTATE_MASTER_TOGGLE,
                 isLocked);
-        RotationPolicy.setRotationLock(mContext, isLocked);
+        RotationPolicy.setRotationLock(mContext, isLocked,
+                /* caller= */ "AutoRotateSwitchBarController#setChecked");
         return true;
     }
 
diff --git a/src/com/android/settings/display/SmartAutoRotatePreferenceController.java b/src/com/android/settings/display/SmartAutoRotatePreferenceController.java
index 311068f..a5c15b6 100644
--- a/src/com/android/settings/display/SmartAutoRotatePreferenceController.java
+++ b/src/com/android/settings/display/SmartAutoRotatePreferenceController.java
@@ -169,7 +169,8 @@
         final boolean isLocked = !isChecked;
         mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_ROTATION_LOCK,
                 isLocked);
-        RotationPolicy.setRotationLock(mContext, isLocked);
+        RotationPolicy.setRotationLock(mContext, isLocked,
+                /* caller= */ "SmartAutoRotatePreferenceController#setChecked");
         return true;
     }
 
diff --git a/src/com/android/settings/gestures/GlobalActionsPanelPreferenceController.java b/src/com/android/settings/gestures/GlobalActionsPanelPreferenceController.java
deleted file mode 100644
index 32a7ba5..0000000
--- a/src/com/android/settings/gestures/GlobalActionsPanelPreferenceController.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2019 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.gestures;
-
-import android.content.Context;
-import android.provider.Settings;
-import android.text.TextUtils;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-public class GlobalActionsPanelPreferenceController extends GesturePreferenceController {
-    private static final String PREF_KEY_VIDEO = "global_actions_panel_video";
-
-    @VisibleForTesting
-    protected static final String ENABLED_SETTING = Settings.Secure.GLOBAL_ACTIONS_PANEL_ENABLED;
-    @VisibleForTesting
-    protected static final String AVAILABLE_SETTING =
-            Settings.Secure.GLOBAL_ACTIONS_PANEL_AVAILABLE;
-
-    @VisibleForTesting
-    protected static final String TOGGLE_KEY = "gesture_global_actions_panel_switch";
-
-    public GlobalActionsPanelPreferenceController(Context context, String key) {
-        super(context, key);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        int enabled = Settings.Secure.getInt(mContext.getContentResolver(), AVAILABLE_SETTING, 0);
-        return enabled == 1 ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
-    }
-
-    @Override
-    public boolean setChecked(boolean isChecked) {
-        return Settings.Secure.putInt(mContext.getContentResolver(), ENABLED_SETTING,
-                isChecked ? 1 : 0);
-    }
-
-    @Override
-    protected String getVideoPrefKey() {
-        return PREF_KEY_VIDEO;
-    }
-
-    @Override
-    public boolean isSliceable() {
-        return TextUtils.equals(getPreferenceKey(), TOGGLE_KEY);
-    }
-
-    @Override
-    public boolean isPublicSlice() {
-        return true;
-    }
-
-    @Override
-    public boolean isChecked() {
-        int enabled = Settings.Secure.getInt(mContext.getContentResolver(), ENABLED_SETTING, 0);
-        return enabled == 1;
-    }
-}
diff --git a/src/com/android/settings/localepicker/TermsOfAddressBaseController.java b/src/com/android/settings/localepicker/TermsOfAddressBaseController.java
new file mode 100644
index 0000000..34c502f
--- /dev/null
+++ b/src/com/android/settings/localepicker/TermsOfAddressBaseController.java
@@ -0,0 +1,82 @@
+/**
+ * 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.localepicker;
+
+import android.app.GrammaticalInflectionManager;
+import android.content.Context;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.TickButtonPreference;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+
+public abstract class TermsOfAddressBaseController extends BasePreferenceController {
+
+    private PreferenceScreen mPreferenceScreen;
+    private MetricsFeatureProvider mMetricsFeatureProvider;
+    private TickButtonPreference mPreference;
+    private GrammaticalInflectionManager mGrammaticalInflectionManager;
+
+    public TermsOfAddressBaseController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+        mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
+        mGrammaticalInflectionManager = context.getSystemService(
+                GrammaticalInflectionManager.class);
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreferenceScreen = screen;
+        mPreference = screen.findPreference(getPreferenceKey());
+        mPreference.setOnPreferenceClickListener(clickedPref -> {
+            mGrammaticalInflectionManager.setSystemWideGrammaticalGender(
+                    getGrammaticalGenderType());
+            setSelected(mPreference);
+            mMetricsFeatureProvider.action(mContext, getMetricsActionKey());
+            return true;
+        });
+        updatePreferences();
+    }
+
+    private void setSelected(TickButtonPreference preference) {
+        for (int i = 1; i < mPreferenceScreen.getPreferenceCount(); i++) {
+            TickButtonPreference pref = (TickButtonPreference) mPreferenceScreen.getPreference(i);
+            pref.setSelected(pref.getKey().equals(preference.getKey()));
+        }
+    }
+
+    private void updatePreferences() {
+        if (mPreference == null) {
+            return;
+        }
+        mPreference.setSelected(
+                mGrammaticalInflectionManager.getSystemGrammaticalGender()
+                        == getGrammaticalGenderType());
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+    protected abstract int getMetricsActionKey();
+
+    protected abstract int getGrammaticalGenderType();
+}
diff --git a/src/com/android/settings/localepicker/TermsOfAddressFeminineController.java b/src/com/android/settings/localepicker/TermsOfAddressFeminineController.java
new file mode 100644
index 0000000..9a46872
--- /dev/null
+++ b/src/com/android/settings/localepicker/TermsOfAddressFeminineController.java
@@ -0,0 +1,45 @@
+/**
+ * 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.localepicker;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.res.Configuration;
+
+public class TermsOfAddressFeminineController extends TermsOfAddressBaseController {
+
+    private static final String KEY_FEMININE = "key_terms_of_address_feminine";
+
+    public TermsOfAddressFeminineController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_FEMININE;
+    }
+
+    @Override
+    protected int getMetricsActionKey() {
+        return SettingsEnums.ACTION_TERMS_OF_ADDRESS_FEMININE;
+    }
+
+    @Override
+    protected int getGrammaticalGenderType() {
+        return Configuration.GRAMMATICAL_GENDER_FEMININE;
+    }
+}
diff --git a/src/com/android/settings/localepicker/TermsOfAddressMasculineController.java b/src/com/android/settings/localepicker/TermsOfAddressMasculineController.java
new file mode 100644
index 0000000..cb39df0
--- /dev/null
+++ b/src/com/android/settings/localepicker/TermsOfAddressMasculineController.java
@@ -0,0 +1,45 @@
+/**
+ * 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.localepicker;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.res.Configuration;
+
+public class TermsOfAddressMasculineController extends TermsOfAddressBaseController {
+
+    private static final String KEY_MASCULINE = "key_terms_of_address_masculine";
+
+    public TermsOfAddressMasculineController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_MASCULINE;
+    }
+
+    @Override
+    protected int getMetricsActionKey() {
+        return SettingsEnums.ACTION_TERMS_OF_ADDRESS_MASCULINE;
+    }
+
+    @Override
+    protected int getGrammaticalGenderType() {
+        return Configuration.GRAMMATICAL_GENDER_MASCULINE;
+    }
+}
diff --git a/src/com/android/settings/localepicker/TermsOfAddressNeutralController.java b/src/com/android/settings/localepicker/TermsOfAddressNeutralController.java
new file mode 100644
index 0000000..e0693b5
--- /dev/null
+++ b/src/com/android/settings/localepicker/TermsOfAddressNeutralController.java
@@ -0,0 +1,45 @@
+/**
+ * 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.localepicker;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.res.Configuration;
+
+public class TermsOfAddressNeutralController extends TermsOfAddressBaseController {
+
+    private static final String KEY_NEUTRAL = "key_terms_of_address_neutral";
+
+    public TermsOfAddressNeutralController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_NEUTRAL;
+    }
+
+    @Override
+    protected int getMetricsActionKey() {
+        return SettingsEnums.ACTION_TERMS_OF_ADDRESS_NEUTRAL;
+    }
+
+    @Override
+    protected int getGrammaticalGenderType() {
+        return Configuration.GRAMMATICAL_GENDER_NEUTRAL;
+    }
+}
diff --git a/src/com/android/settings/localepicker/TermsOfAddressNotSpecifiedController.java b/src/com/android/settings/localepicker/TermsOfAddressNotSpecifiedController.java
new file mode 100644
index 0000000..4e2e450
--- /dev/null
+++ b/src/com/android/settings/localepicker/TermsOfAddressNotSpecifiedController.java
@@ -0,0 +1,45 @@
+/**
+ * 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.localepicker;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.res.Configuration;
+
+public class TermsOfAddressNotSpecifiedController extends TermsOfAddressBaseController {
+
+    private static final String KEY_NOT_SPECIFIED = "key_terms_of_address_not_specified";
+
+    public TermsOfAddressNotSpecifiedController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_NOT_SPECIFIED;
+    }
+
+    @Override
+    protected int getMetricsActionKey() {
+        return SettingsEnums.ACTION_TERMS_OF_ADDRESS_NOT_SPECIFIED;
+    }
+
+    @Override
+    protected int getGrammaticalGenderType() {
+        return Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
+    }
+}
diff --git a/src/com/android/settings/network/MobileNetworkRepository.java b/src/com/android/settings/network/MobileNetworkRepository.java
index 5d6ad33..80c5464 100644
--- a/src/com/android/settings/network/MobileNetworkRepository.java
+++ b/src/com/android/settings/network/MobileNetworkRepository.java
@@ -40,6 +40,7 @@
 import androidx.annotation.GuardedBy;
 import androidx.lifecycle.LifecycleOwner;
 
+import com.android.internal.telephony.flags.Flags;
 import com.android.settings.network.telephony.MobileNetworkUtils;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
@@ -703,9 +704,10 @@
                         Log.d(TAG, "insert subInfo to subInfoEntity, subInfo = " + subInfo);
                     }
                     if (subInfo.isEmbedded()
-                            && subInfo.getProfileClass() == PROFILE_CLASS_PROVISIONING) {
+                        && (subInfo.getProfileClass() == PROFILE_CLASS_PROVISIONING
+                        || (Flags.oemEnabledSatelliteFlag() && subInfo.isNtn()))) {
                         if (DEBUG) {
-                            Log.d(TAG, "Do not insert the provision eSIM");
+                            Log.d(TAG, "Do not insert the provisioning or satellite eSIM");
                         }
                         continue;
                     }
diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java
index eb50cea..793fecc 100644
--- a/src/com/android/settings/network/NetworkProviderSettings.java
+++ b/src/com/android/settings/network/NetworkProviderSettings.java
@@ -190,7 +190,10 @@
     @VisibleForTesting
     final Runnable mUpdateWifiEntryPreferencesRunnable = () -> {
         updateWifiEntryPreferences();
-        getView().postDelayed(mRemoveLoadingRunnable, 10);
+        View view = getView();
+        if (view != null) {
+            view.postDelayed(mRemoveLoadingRunnable, 10);
+        }
     };
     @VisibleForTesting
     final Runnable mHideProgressBarRunnable = () -> {
diff --git a/src/com/android/settings/network/SubscriptionsPreferenceController.java b/src/com/android/settings/network/SubscriptionsPreferenceController.java
index 9cd49c8..cc62189 100644
--- a/src/com/android/settings/network/SubscriptionsPreferenceController.java
+++ b/src/com/android/settings/network/SubscriptionsPreferenceController.java
@@ -265,9 +265,8 @@
 
     /**@return {@code true} if subId is the default data sub. **/
     private boolean isDds(int subId) {
-        return mSubscriptionManager.getDefaultDataSubscriptionInfo() != null
-                && mSubscriptionManager.getDefaultDataSubscriptionInfo().getSubscriptionId()
-                == subId;
+        SubscriptionInfo info = mSubscriptionManager.getDefaultDataSubscriptionInfo();
+        return info != null && info.getSubscriptionId() == subId;
     }
 
     private CharSequence getMobilePreferenceSummary(int subId) {
diff --git a/src/com/android/settings/network/apn/ApnEditPageProvider.kt b/src/com/android/settings/network/apn/ApnEditPageProvider.kt
index f2c3325..9f3947f 100644
--- a/src/com/android/settings/network/apn/ApnEditPageProvider.kt
+++ b/src/com/android/settings/network/apn/ApnEditPageProvider.kt
@@ -36,6 +36,7 @@
 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.SwitchPreference
 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
 import com.android.settingslib.spa.widget.scaffold.RegularScaffold
@@ -123,7 +124,10 @@
                 stringResource(R.string.apn_user),
                 enabled = apnData.userNameEnabled
             ) { apnData = apnData.copy(userName = it) }
-            // TODO: password
+            SettingsTextFieldPassword(
+                apnData.passWord,
+                stringResource(R.string.apn_password)
+            ) { apnData = apnData.copy(passWord = it) }
             SettingsOutlinedTextField(
                 apnData.server,
                 stringResource(R.string.apn_server),
diff --git a/src/com/android/settings/network/apn/ApnStatus.kt b/src/com/android/settings/network/apn/ApnStatus.kt
index 06d8cfb..5d64142 100644
--- a/src/com/android/settings/network/apn/ApnStatus.kt
+++ b/src/com/android/settings/network/apn/ApnStatus.kt
@@ -71,6 +71,14 @@
     var mvnoValueEnabled = false
 }
 
+/**
+ * Initialize the selected Bearer Selected Options according to bearer.
+ * @param bearer Initialized bearer options.
+ * @param bearerBitmask Initialized bearer bitmask, often multiple bearer options may be included.
+ * @param context The context to get bearerValues.
+ *
+ * @return An error message if the apn data is invalid, otherwise return null.
+ */
 fun getBearerSelectedOptionsState(
     bearer: Int,
     bearerBitmask: Int,
diff --git a/src/com/android/settings/notification/history/NotificationSbnAdapter.java b/src/com/android/settings/notification/history/NotificationSbnAdapter.java
index 1d61ae7..c556b55 100644
--- a/src/com/android/settings/notification/history/NotificationSbnAdapter.java
+++ b/src/com/android/settings/notification/history/NotificationSbnAdapter.java
@@ -120,7 +120,7 @@
             holder.setDividerVisible(position < (mValues.size() -1));
             int userId = normalizeUserId(sbn);
             if (!mUserBadgeCache.containsKey(userId)) {
-                Drawable profile = mContext.getPackageManager().getUserBadgeForDensity(
+                Drawable profile = mContext.getPackageManager().getUserBadgeForDensityNoBackground(
                         UserHandle.of(userId), 0);
                 mUserBadgeCache.put(userId, profile);
             }
diff --git a/src/com/android/settings/search/SettingsSearchIndexablesProvider.java b/src/com/android/settings/search/SettingsSearchIndexablesProvider.java
index 3b10c09..3b04186 100644
--- a/src/com/android/settings/search/SettingsSearchIndexablesProvider.java
+++ b/src/com/android/settings/search/SettingsSearchIndexablesProvider.java
@@ -454,7 +454,7 @@
             // Skip Settings injected items because they should be indexed in the sub-pages.
             return false;
         }
-        return true;
+        return tile.isSearchable();
     }
 
     private static Object[] createIndexableRawColumnObjects(SearchIndexableRaw raw) {
diff --git a/src/com/android/settings/sim/CallsSimListDialogFragment.java b/src/com/android/settings/sim/CallsSimListDialogFragment.java
index cbee634..bc0ab08 100644
--- a/src/com/android/settings/sim/CallsSimListDialogFragment.java
+++ b/src/com/android/settings/sim/CallsSimListDialogFragment.java
@@ -26,6 +26,8 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 
+import com.android.internal.telephony.flags.Flags;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -56,7 +58,8 @@
 
             SubscriptionInfo info = subscriptionManager.getActiveSubscriptionInfo(subId);
             if (info == null || (info.isEmbedded()
-                    && info.getProfileClass() == PROFILE_CLASS_PROVISIONING)) {
+                && (info.getProfileClass() == PROFILE_CLASS_PROVISIONING
+                || (Flags.oemEnabledSatelliteFlag() && info.isNtn())))) {
                 continue;
             }
             result.add(subscriptionManager.getActiveSubscriptionInfo(subId));
diff --git a/src/com/android/settings/sim/PreferredSimDialogFragment.java b/src/com/android/settings/sim/PreferredSimDialogFragment.java
index 50eb993..c1e98f0 100644
--- a/src/com/android/settings/sim/PreferredSimDialogFragment.java
+++ b/src/com/android/settings/sim/PreferredSimDialogFragment.java
@@ -32,6 +32,7 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.appcompat.app.AlertDialog;
 
+import com.android.internal.telephony.flags.Flags;
 import com.android.settings.R;
 import com.android.settings.network.SubscriptionUtil;
 
@@ -98,7 +99,8 @@
 
         final SubscriptionInfo info = getPreferredSubscription();
         if (info == null || (info.isEmbedded()
-                && info.getProfileClass() == PROFILE_CLASS_PROVISIONING)) {
+            && (info.getProfileClass() == PROFILE_CLASS_PROVISIONING
+            || (Flags.oemEnabledSatelliteFlag() && info.isNtn())))) {
             dismiss();
             return;
         }
diff --git a/src/com/android/settings/sim/SelectSpecificDataSimDialogFragment.java b/src/com/android/settings/sim/SelectSpecificDataSimDialogFragment.java
index 6ac0067..218efc0 100644
--- a/src/com/android/settings/sim/SelectSpecificDataSimDialogFragment.java
+++ b/src/com/android/settings/sim/SelectSpecificDataSimDialogFragment.java
@@ -35,6 +35,7 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.appcompat.app.AlertDialog;
 
+import com.android.internal.telephony.flags.Flags;
 import com.android.settings.R;
 import com.android.settings.network.SubscriptionUtil;
 
@@ -133,10 +134,13 @@
             return;
         }
 
-        if ((newSubInfo.isEmbedded() && newSubInfo.getProfileClass() == PROFILE_CLASS_PROVISIONING)
-                || (currentDataSubInfo.isEmbedded()
-                && currentDataSubInfo.getProfileClass() == PROFILE_CLASS_PROVISIONING)) {
-            Log.d(TAG, "do not set the provision eSIM");
+        if ((newSubInfo.isEmbedded()
+            && (newSubInfo.getProfileClass() == PROFILE_CLASS_PROVISIONING
+            || (Flags.oemEnabledSatelliteFlag() && newSubInfo.isNtn())))
+            || (currentDataSubInfo.isEmbedded()
+            && (currentDataSubInfo.getProfileClass() == PROFILE_CLASS_PROVISIONING
+            || (Flags.oemEnabledSatelliteFlag() && currentDataSubInfo.isNtn())))) {
+            Log.d(TAG, "do not set the provisioning or satellite eSIM");
             dismiss();
             return;
         }
diff --git a/src/com/android/settings/sim/SimListDialogFragment.java b/src/com/android/settings/sim/SimListDialogFragment.java
index 2763211..4a478e9 100644
--- a/src/com/android/settings/sim/SimListDialogFragment.java
+++ b/src/com/android/settings/sim/SimListDialogFragment.java
@@ -39,6 +39,7 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.appcompat.app.AlertDialog;
 
+import com.android.internal.telephony.flags.Flags;
 import com.android.settings.R;
 import com.android.settings.network.SubscriptionUtil;
 
@@ -141,9 +142,10 @@
             return;
         }
 
-        // Remove the provision eSIM from the subscription list.
+        // Remove the provisioning or satellite eSIM from the subscription list.
         currentSubscriptions.removeIf(info -> info.isEmbedded()
-                && info.getProfileClass() == PROFILE_CLASS_PROVISIONING);
+            && (info.getProfileClass() == PROFILE_CLASS_PROVISIONING
+            || (Flags.oemEnabledSatelliteFlag() && info.isNtn())));
 
         boolean includeAskEveryTime = getArguments().getBoolean(KEY_INCLUDE_ASK_EVERY_TIME);
         boolean isCancelItemShowed = getArguments().getBoolean(KEY_SHOW_CANCEL_ITEM);
diff --git a/src/com/android/settings/wifi/WifiDialog2.kt b/src/com/android/settings/wifi/WifiDialog2.kt
index 3e5f6fe..a0d215a 100644
--- a/src/com/android/settings/wifi/WifiDialog2.kt
+++ b/src/com/android/settings/wifi/WifiDialog2.kt
@@ -25,6 +25,7 @@
 import android.widget.Button
 import android.widget.ImageButton
 import android.widget.TextView
+import androidx.annotation.OpenForTesting
 import androidx.appcompat.app.AlertDialog
 import com.android.settings.R
 import com.android.settingslib.RestrictedLockUtils
@@ -34,7 +35,8 @@
 /**
  * Dialog for users to edit a Wi-Fi network.
  */
-class WifiDialog2 @JvmOverloads constructor(
+@OpenForTesting
+open class WifiDialog2 @JvmOverloads constructor(
     context: Context,
     private val listener: WifiDialog2Listener,
     val wifiEntry: WifiEntry?,
diff --git a/tests/robotests/Android.bp b/tests/robotests/Android.bp
index 910bbbd..fbfd888 100644
--- a/tests/robotests/Android.bp
+++ b/tests/robotests/Android.bp
@@ -61,6 +61,7 @@
         "flag-junit",
         "aconfig_settings_flags_lib",
         "platform-test-annotations",
+        "Settings-testutils2",
     ],
 
     libs: [
diff --git a/tests/robotests/assets/exempt_slice_controller_not_in_xml b/tests/robotests/assets/exempt_slice_controller_not_in_xml
index 385b702..93bd9f3 100644
--- a/tests/robotests/assets/exempt_slice_controller_not_in_xml
+++ b/tests/robotests/assets/exempt_slice_controller_not_in_xml
@@ -3,9 +3,11 @@
 com.android.settings.biometrics.face.FaceSettingsAttentionPreferenceController
 com.android.settings.display.DeviceStateAutoRotateSettingController
 com.android.settings.display.SmartAutoRotatePreferenceController
+com.android.settings.gestures.OneHandedMainSwitchPreferenceController
 com.android.settings.network.telephony.MmsMessagePreferenceController
 com.android.settings.network.telephony.AutoDataSwitchPreferenceController
 com.android.settings.network.telephony.Enhanced4gBasePreferenceController
+com.android.settings.notification.RingVolumePreferenceController
 com.android.settings.testutils.FakeToggleController
 com.android.settings.testutils.FakeSliderController
 com.android.settings.testutils.FakeInvalidSliderController
diff --git a/tests/robotests/src/com/android/settings/biometrics/combination/CombinedBiometricProfileSettingsTest.java b/tests/robotests/src/com/android/settings/biometrics/combination/CombinedBiometricProfileSettingsTest.java
index 4781f56..43d2add 100644
--- a/tests/robotests/src/com/android/settings/biometrics/combination/CombinedBiometricProfileSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/combination/CombinedBiometricProfileSettingsTest.java
@@ -72,6 +72,7 @@
 
 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;
@@ -407,6 +408,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void testClickFaceUnlock_inMultiWindow_withoutEnrolledFp_showsDialog() {
         testClickFaceUnlock(true /* isInMultiWindow */, false /*hasEnrolledFace*/);
         verifyShowsDialogAfterClickingUnlock(mFragment.getFacePreferenceKey());
diff --git a/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollEducationTest.java b/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollEducationTest.java
index b4dddde..474ea8c 100644
--- a/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollEducationTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollEducationTest.java
@@ -50,6 +50,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -127,6 +128,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void testFaceEnrollEducation_hasHeader() {
         setupActivity();
         CharSequence headerText = getGlifLayout().getHeaderText();
diff --git a/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java b/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java
index 3165d05..459e377 100644
--- a/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java
@@ -76,6 +76,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -282,6 +283,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void testOnCreateToGenerateChallenge() {
         setupActivityWithGenerateChallenge(
                 new Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 1L));
@@ -432,6 +434,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void testFaceEnrollIntroduction_onStartRegisteredPostureChangeCallback() {
         setupActivityForPosture();
         mSpyActivity.onStart();
diff --git a/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceControllerTest.java
index 5f56fa7..ae35972 100644
--- a/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceControllerTest.java
@@ -32,6 +32,7 @@
 import com.android.settingslib.widget.LayoutPreference;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -44,6 +45,7 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
 
+@Ignore("b/295325503")
 @RunWith(RobolectricTestRunner.class)
 @Config(shadows = {ShadowUserManager.class})
 public class FaceSettingsRemoveButtonPreferenceControllerTest {
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
index fa0cd2b..4de369e 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
@@ -70,6 +70,7 @@
 import com.google.android.setupdesign.GlifLayout;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -85,6 +86,7 @@
 import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 
+@Ignore("b/295325503")
 @RunWith(RobolectricTestRunner.class)
 @LooperMode(LooperMode.Mode.LEGACY)
 public class FingerprintEnrollEnrollingTest {
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java
index 8727153..72f1ab8 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java
@@ -65,6 +65,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -556,6 +557,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void fingerprintEnrollFindSensor_activityApplyDarkLightStyle() {
         setupActivity_onSfpsDevice();
         verifySidecar_onRearOrSfpsDevice();
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFinishTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFinishTest.java
index e238a0e..fa33f9c 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFinishTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFinishTest.java
@@ -35,6 +35,7 @@
 import com.google.android.setupcompat.template.FooterBarMixin;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.Robolectric;
@@ -115,6 +116,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void onActivityResult_fingerprintCountIsOne_fingerprintSuggestionActivityEnabled() {
         Shadows.shadowOf((FingerprintManager) mFingerprintManager).setDefaultFingerprints(1);
 
@@ -135,6 +137,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void clickNext_fingerprintCountIsOne_fngerprintSuggestionActivityEnabled() {
         Shadows.shadowOf((FingerprintManager) mFingerprintManager).setDefaultFingerprints(1);
 
@@ -155,6 +158,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void onBackPressed_fingerprintCountIsOne_fngerprintSuggestionActivityEnabled() {
         Shadows.shadowOf((FingerprintManager) mFingerprintManager).setDefaultFingerprints(1);
 
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
index 5f0f2b9..d381975 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
@@ -52,7 +52,9 @@
 public class ConnectedDeviceDashboardFragmentTest {
     private static final String KEY_NEARBY_DEVICES = "bt_nearby_slice";
     private static final String KEY_DISCOVERABLE_FOOTER = "discoverable_footer";
-    private static final String KEY_SEE_ALL = "previously_connected_devices_see_all";
+    private static final String KEY_SAVED_DEVICE_SEE_ALL = "previously_connected_devices_see_all";
+    private static final String KEY_FAST_PAIR_DEVICE_SEE_ALL = "fast_pair_devices_see_all";
+    private static final String KEY_FAST_PAIR_DEVICE_LIST = "fast_pair_devices";
     private static final String KEY_ADD_BT_DEVICES = "add_bt_devices";
     private static final String SETTINGS_PACKAGE_NAME = "com.android.settings";
     private static final String SYSTEMUI_PACKAGE_NAME = "com.android.systemui";
@@ -92,7 +94,8 @@
                 .getNonIndexableKeys(mContext);
 
         assertThat(niks).containsExactly(KEY_CONNECTED_DEVICES, KEY_AVAILABLE_DEVICES,
-                KEY_NEARBY_DEVICES, KEY_DISCOVERABLE_FOOTER, KEY_SEE_ALL);
+                KEY_NEARBY_DEVICES, KEY_DISCOVERABLE_FOOTER, KEY_SAVED_DEVICE_SEE_ALL,
+                KEY_FAST_PAIR_DEVICE_SEE_ALL, KEY_FAST_PAIR_DEVICE_LIST);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/core/InstrumentedPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/core/InstrumentedPreferenceFragmentTest.java
index dc173e5..838edc6 100644
--- a/tests/robotests/src/com/android/settings/core/InstrumentedPreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/core/InstrumentedPreferenceFragmentTest.java
@@ -23,6 +23,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.Context;
 import android.os.Bundle;
 
 import androidx.fragment.app.FragmentActivity;
@@ -38,6 +39,7 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.util.ReflectionHelpers;
 
@@ -53,7 +55,7 @@
     private PreferenceManager mPreferenceManager;
     @Mock
     private FragmentActivity mActivity;
-
+    private Context mContext;
     private InstrumentedPreferenceFragmentTestable mFragment;
 
     @Before
@@ -61,7 +63,9 @@
         MockitoAnnotations.initMocks(this);
         when(mPreferenceManager.getPreferenceScreen()).thenReturn(mScreen);
 
+        mContext = RuntimeEnvironment.application;
         mFragment = spy(new InstrumentedPreferenceFragmentTestable());
+        when(mFragment.getContext()).thenReturn(mContext);
         ReflectionHelpers.setField(mFragment, "mPreferenceManager", mPreferenceManager);
     }
 
diff --git a/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java b/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java
index aab67be..9c93606 100644
--- a/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/ChartDataUsagePreferenceTest.java
@@ -31,9 +31,9 @@
 
 import com.android.settings.R;
 import com.android.settings.datausage.ChartDataUsagePreference.DataUsageSummaryNode;
+import com.android.settings.datausage.lib.NetworkCycleChartData;
+import com.android.settings.datausage.lib.NetworkUsageData;
 import com.android.settings.widget.UsageView;
-import com.android.settingslib.net.NetworkCycleChartData;
-import com.android.settingslib.net.NetworkCycleData;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -55,7 +55,7 @@
     // Test bucket end date, 22 Mar 2018 00:00:00
     private static final long TIMESTAMP_END = 1521676800000L;
 
-    private List<NetworkCycleData> mNetworkCycleData;
+    private List<NetworkUsageData> mNetworkCycleData;
     private NetworkCycleChartData mNetworkCycleChartData;
     private ChartDataUsagePreference mPreference;
     private Activity mActivity;
@@ -79,6 +79,9 @@
         final ArgumentCaptor<SparseIntArray> pointsCaptor =
                 ArgumentCaptor.forClass(SparseIntArray.class);
         createTestNetworkData();
+        mPreference.setTime(
+                mNetworkCycleChartData.getTotal().getStartTime(),
+                mNetworkCycleChartData.getTotal().getEndTime());
         mPreference.setNetworkCycleData(mNetworkCycleChartData);
 
         mPreference.calcPoints(usageView, mNetworkCycleData.subList(0, 5));
@@ -95,6 +98,9 @@
         final ArgumentCaptor<SparseIntArray> pointsCaptor =
                 ArgumentCaptor.forClass(SparseIntArray.class);
         createTestNetworkData();
+        mPreference.setTime(
+                mNetworkCycleChartData.getTotal().getStartTime(),
+                mNetworkCycleChartData.getTotal().getEndTime());
         mPreference.setNetworkCycleData(mNetworkCycleChartData);
 
         mPreference.calcPoints(usageView, mNetworkCycleData.subList(2, 7));
@@ -110,39 +116,62 @@
     public void calcPoints_shouldNotDrawPointForFutureDate() {
         final UsageView usageView = mock(UsageView.class);
         final ArgumentCaptor<SparseIntArray> pointsCaptor =
-            ArgumentCaptor.forClass(SparseIntArray.class);
+                ArgumentCaptor.forClass(SparseIntArray.class);
         final long tonight = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(12);
         mNetworkCycleData = new ArrayList<>();
         // add test usage data for last 5 days
-        mNetworkCycleData.add(createNetworkCycleData(
-            tonight - TimeUnit.DAYS.toMillis(5), tonight - TimeUnit.DAYS.toMillis(4), 743823454L));
-        mNetworkCycleData.add(createNetworkCycleData(
-            tonight - TimeUnit.DAYS.toMillis(4), tonight - TimeUnit.DAYS.toMillis(3), 64396L));
-        mNetworkCycleData.add(createNetworkCycleData(
-            tonight - TimeUnit.DAYS.toMillis(3), tonight - TimeUnit.DAYS.toMillis(2), 2832L));
-        mNetworkCycleData.add(createNetworkCycleData(
-            tonight - TimeUnit.DAYS.toMillis(2), tonight - TimeUnit.DAYS.toMillis(1), 83849690L));
-        mNetworkCycleData.add(createNetworkCycleData(
-            tonight - TimeUnit.DAYS.toMillis(1), tonight, 1883657L));
+        mNetworkCycleData.add(new NetworkUsageData(
+                tonight - TimeUnit.DAYS.toMillis(5),
+                tonight - TimeUnit.DAYS.toMillis(4),
+                743823454L));
+        mNetworkCycleData.add(new NetworkUsageData(
+                tonight - TimeUnit.DAYS.toMillis(4),
+                tonight - TimeUnit.DAYS.toMillis(3),
+                64396L));
+        mNetworkCycleData.add(new NetworkUsageData(
+                tonight - TimeUnit.DAYS.toMillis(3),
+                tonight - TimeUnit.DAYS.toMillis(2),
+                2832L));
+        mNetworkCycleData.add(new NetworkUsageData(
+                tonight - TimeUnit.DAYS.toMillis(2),
+                tonight - TimeUnit.DAYS.toMillis(1),
+                83849690L));
+        mNetworkCycleData.add(new NetworkUsageData(
+                tonight - TimeUnit.DAYS.toMillis(1), tonight, 1883657L));
         // add test usage data for next 5 days
-        mNetworkCycleData.add(createNetworkCycleData(
-            tonight, tonight + TimeUnit.DAYS.toMillis(1), 0L));
-        mNetworkCycleData.add(createNetworkCycleData(
-            tonight + TimeUnit.DAYS.toMillis(1), tonight + TimeUnit.DAYS.toMillis(2), 0L));
-        mNetworkCycleData.add(createNetworkCycleData(
-            tonight + TimeUnit.DAYS.toMillis(2), tonight + TimeUnit.DAYS.toMillis(3), 0L));
-        mNetworkCycleData.add(createNetworkCycleData(
-            tonight + TimeUnit.DAYS.toMillis(3), tonight + TimeUnit.DAYS.toMillis(4), 0L));
-        mNetworkCycleData.add(createNetworkCycleData(
-            tonight + TimeUnit.DAYS.toMillis(4), tonight + TimeUnit.DAYS.toMillis(5), 0L));
-        mNetworkCycleData.add(createNetworkCycleData(
-            tonight + TimeUnit.DAYS.toMillis(5), tonight + TimeUnit.DAYS.toMillis(6), 0L));
+        mNetworkCycleData.add(new NetworkUsageData(
+                tonight, tonight + TimeUnit.DAYS.toMillis(1), 0L));
+        mNetworkCycleData.add(new NetworkUsageData(
+                tonight + TimeUnit.DAYS.toMillis(1),
+                tonight + TimeUnit.DAYS.toMillis(2),
+                0L));
+        mNetworkCycleData.add(new NetworkUsageData(
+                tonight + TimeUnit.DAYS.toMillis(2),
+                tonight + TimeUnit.DAYS.toMillis(3),
+                0L));
+        mNetworkCycleData.add(new NetworkUsageData(
+                tonight + TimeUnit.DAYS.toMillis(3),
+                tonight + TimeUnit.DAYS.toMillis(4),
+                0L));
+        mNetworkCycleData.add(new NetworkUsageData(
+                tonight + TimeUnit.DAYS.toMillis(4),
+                tonight + TimeUnit.DAYS.toMillis(5),
+                0L));
+        mNetworkCycleData.add(new NetworkUsageData(
+                tonight + TimeUnit.DAYS.toMillis(5),
+                tonight + TimeUnit.DAYS.toMillis(6),
+                0L));
 
-        final NetworkCycleChartData.Builder builder = new NetworkCycleChartData.Builder();
-        builder.setUsageBuckets(mNetworkCycleData)
-            .setStartTime(tonight - TimeUnit.DAYS.toMillis(5))
-            .setEndTime(tonight + TimeUnit.DAYS.toMillis(6));
-        mNetworkCycleChartData = builder.build();
+        mNetworkCycleChartData = new NetworkCycleChartData(
+                new NetworkUsageData(
+                        tonight - TimeUnit.DAYS.toMillis(5),
+                        tonight + TimeUnit.DAYS.toMillis(6),
+                        0),
+                mNetworkCycleData
+        );
+        mPreference.setTime(
+                mNetworkCycleChartData.getTotal().getStartTime(),
+                mNetworkCycleChartData.getTotal().getEndTime());
         mPreference.setNetworkCycleData(mNetworkCycleChartData);
 
         mPreference.calcPoints(usageView, mNetworkCycleData);
@@ -170,6 +199,9 @@
         final TextView labelStart = (TextView) mHolder.findViewById(R.id.label_start);
         final TextView labelEnd = (TextView) mHolder.findViewById(R.id.label_end);
         createTestNetworkData();
+        mPreference.setTime(
+                mNetworkCycleChartData.getTotal().getStartTime(),
+                mNetworkCycleChartData.getTotal().getEndTime());
         mPreference.setNetworkCycleData(mNetworkCycleChartData);
 
         mPreference.onBindViewHolder(mHolder);
@@ -198,38 +230,33 @@
     private void createTestNetworkData() {
         mNetworkCycleData = new ArrayList<>();
         // create 10 arbitrary network data
-        mNetworkCycleData.add(createNetworkCycleData(1521583200000L, 1521586800000L, 743823454L));
-        mNetworkCycleData.add(createNetworkCycleData(1521586800000L, 1521590400000L, 64396L));
-        mNetworkCycleData.add(createNetworkCycleData(1521590400000L, 1521655200000L, 2832L));
-        mNetworkCycleData.add(createNetworkCycleData(1521655200000L, 1521658800000L, 83849690L));
-        mNetworkCycleData.add(createNetworkCycleData(1521658800000L, 1521662400000L, 1883657L));
-        mNetworkCycleData.add(createNetworkCycleData(1521662400000L, 1521666000000L, 705259L));
-        mNetworkCycleData.add(createNetworkCycleData(1521666000000L, 1521669600000L, 216169L));
-        mNetworkCycleData.add(createNetworkCycleData(1521669600000L, 1521673200000L, 6069175L));
-        mNetworkCycleData.add(createNetworkCycleData(1521673200000L, 1521676800000L, 120389L));
-        mNetworkCycleData.add(createNetworkCycleData(1521676800000L, 1521678800000L, 29947L));
+        mNetworkCycleData.add(new NetworkUsageData(1521583200000L, 1521586800000L, 743823454L));
+        mNetworkCycleData.add(new NetworkUsageData(1521586800000L, 1521590400000L, 64396L));
+        mNetworkCycleData.add(new NetworkUsageData(1521590400000L, 1521655200000L, 2832L));
+        mNetworkCycleData.add(new NetworkUsageData(1521655200000L, 1521658800000L, 83849690L));
+        mNetworkCycleData.add(new NetworkUsageData(1521658800000L, 1521662400000L, 1883657L));
+        mNetworkCycleData.add(new NetworkUsageData(1521662400000L, 1521666000000L, 705259L));
+        mNetworkCycleData.add(new NetworkUsageData(1521666000000L, 1521669600000L, 216169L));
+        mNetworkCycleData.add(new NetworkUsageData(1521669600000L, 1521673200000L, 6069175L));
+        mNetworkCycleData.add(new NetworkUsageData(1521673200000L, 1521676800000L, 120389L));
+        mNetworkCycleData.add(new NetworkUsageData(1521676800000L, 1521678800000L, 29947L));
 
-        final NetworkCycleChartData.Builder builder = new NetworkCycleChartData.Builder();
-        builder.setUsageBuckets(mNetworkCycleData)
-            .setStartTime(TIMESTAMP_START)
-            .setEndTime(TIMESTAMP_END);
-        mNetworkCycleChartData = builder.build();
+        mNetworkCycleChartData = new NetworkCycleChartData(
+                new NetworkUsageData(TIMESTAMP_START, TIMESTAMP_END, 0),
+                mNetworkCycleData
+        );
     }
 
     private void createSomeSamePercentageNetworkData() {
         mNetworkCycleData = new ArrayList<>();
-        mNetworkCycleData.add(createNetworkCycleData(1521583200000L, 1521586800000L, 100));//33%
-        mNetworkCycleData.add(createNetworkCycleData(1521586800000L, 1521590400000L, 1));  //33%
-        mNetworkCycleData.add(createNetworkCycleData(1521590400000L, 1521655200000L, 0));  //33%
-        mNetworkCycleData.add(createNetworkCycleData(1521655200000L, 1521658800000L, 0));  //33%
-        mNetworkCycleData.add(createNetworkCycleData(1521658800000L, 1521662400000L, 200));//99%
-        mNetworkCycleData.add(createNetworkCycleData(1521662400000L, 1521666000000L, 1));  //99%
-        mNetworkCycleData.add(createNetworkCycleData(1521666000000L, 1521669600000L, 1));  //100
-        mNetworkCycleData.add(createNetworkCycleData(1521669600000L, 1521673200000L, 0));  //100%
+        mNetworkCycleData.add(new NetworkUsageData(1521583200000L, 1521586800000L, 100)); //33%
+        mNetworkCycleData.add(new NetworkUsageData(1521586800000L, 1521590400000L, 1));   //33%
+        mNetworkCycleData.add(new NetworkUsageData(1521590400000L, 1521655200000L, 0));   //33%
+        mNetworkCycleData.add(new NetworkUsageData(1521655200000L, 1521658800000L, 0));   //33%
+        mNetworkCycleData.add(new NetworkUsageData(1521658800000L, 1521662400000L, 200)); //99%
+        mNetworkCycleData.add(new NetworkUsageData(1521662400000L, 1521666000000L, 1));   //99%
+        mNetworkCycleData.add(new NetworkUsageData(1521666000000L, 1521669600000L, 1));   //100
+        mNetworkCycleData.add(new NetworkUsageData(1521669600000L, 1521673200000L, 0));   //100%
     }
 
-    private NetworkCycleData createNetworkCycleData(long start, long end, long usage) {
-        return new NetworkCycleData.Builder()
-            .setStartTime(start).setEndTime(end).setTotalUsage(usage).build();
-    }
 }
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
deleted file mode 100644
index 1268032..0000000
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (C) 2018 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.datausage;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.net.NetworkTemplate;
-import android.os.Bundle;
-import android.os.UserManager;
-import android.provider.Settings;
-
-import androidx.annotation.NonNull;
-import androidx.loader.app.LoaderManager;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceManager;
-
-import com.android.settings.datausage.lib.BillingCycleRepository;
-import com.android.settings.network.MobileDataEnabledListener;
-import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settings.widget.LoadingViewController;
-import com.android.settingslib.NetworkPolicyEditor;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
-import com.android.settingslib.net.NetworkCycleChartData;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Spy;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.android.controller.ActivityController;
-import org.robolectric.annotation.Config;
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.util.ReflectionHelpers;
-
-import java.util.Collections;
-import java.util.List;
-
-@RunWith(RobolectricTestRunner.class)
-@Config(shadows = DataUsageListTest.ShadowDataUsageBaseFragment.class)
-public class DataUsageListTest {
-    @Rule
-    public MockitoRule mMockitoRule = MockitoJUnit.rule();
-
-    @Mock
-    private MobileDataEnabledListener mMobileDataEnabledListener;
-    @Mock
-    private TemplatePreference.NetworkServices mNetworkServices;
-    @Mock
-    private LoaderManager mLoaderManager;
-    @Mock
-    private UserManager mUserManager;
-    @Mock
-    private BillingCycleRepository mBillingCycleRepository;
-    @Mock
-    private DataUsageListHeaderController mDataUsageListHeaderController;
-
-    private Activity mActivity;
-
-    @Spy
-    private TestDataUsageList mDataUsageList;
-
-    @Before
-    public void setUp() {
-        FakeFeatureFactory.setupForTest();
-        final ActivityController<Activity> mActivityController =
-                Robolectric.buildActivity(Activity.class);
-        mActivity = spy(mActivityController.get());
-        mNetworkServices.mPolicyEditor = mock(NetworkPolicyEditor.class);
-        mDataUsageList.mDataStateListener = mMobileDataEnabledListener;
-
-        doReturn(mActivity).when(mDataUsageList).getContext();
-        doReturn(mUserManager).when(mActivity).getSystemService(UserManager.class);
-        doReturn(false).when(mUserManager).isGuestUser();
-        ReflectionHelpers.setField(mDataUsageList, "mDataStateListener",
-                mMobileDataEnabledListener);
-        ReflectionHelpers.setField(mDataUsageList, "services", mNetworkServices);
-        doReturn(mLoaderManager).when(mDataUsageList).getLoaderManager();
-        mDataUsageList.mLoadingViewController = mock(LoadingViewController.class);
-        doNothing().when(mDataUsageList).updateSubscriptionInfoEntity();
-        when(mBillingCycleRepository.isBandwidthControlEnabled()).thenReturn(true);
-        mDataUsageList.mDataUsageListHeaderController = mDataUsageListHeaderController;
-    }
-
-    @Test
-    public void onCreate_isNotGuestUser_shouldNotFinish() {
-        mDataUsageList.mTemplate = mock(NetworkTemplate.class);
-        doReturn(false).when(mUserManager).isGuestUser();
-        doNothing().when(mDataUsageList).processArgument();
-
-        mDataUsageList.onCreate(null);
-
-        verify(mDataUsageList, never()).finish();
-    }
-
-    @Test
-    public void onCreate_isGuestUser_shouldFinish() {
-        doReturn(true).when(mUserManager).isGuestUser();
-
-        mDataUsageList.onCreate(null);
-
-        verify(mDataUsageList).finish();
-    }
-
-    @Test
-    public void resume_shouldListenDataStateChange() {
-        mDataUsageList.onCreate(null);
-        ReflectionHelpers.setField(
-                mDataUsageList, "mVisibilityLoggerMixin", mock(VisibilityLoggerMixin.class));
-        ReflectionHelpers.setField(
-                mDataUsageList, "mPreferenceManager", mock(PreferenceManager.class));
-
-        mDataUsageList.onResume();
-
-        verify(mMobileDataEnabledListener).start(anyInt());
-
-        mDataUsageList.onPause();
-    }
-
-    @Test
-    public void pause_shouldUnlistenDataStateChange() {
-        mDataUsageList.onCreate(null);
-        ReflectionHelpers.setField(
-                mDataUsageList, "mVisibilityLoggerMixin", mock(VisibilityLoggerMixin.class));
-        ReflectionHelpers.setField(
-                mDataUsageList, "mPreferenceManager", mock(PreferenceManager.class));
-
-        mDataUsageList.onResume();
-        mDataUsageList.onPause();
-
-        verify(mMobileDataEnabledListener).stop();
-    }
-
-    @Test
-    public void processArgument_shouldGetTemplateFromArgument() {
-        final Bundle args = new Bundle();
-        args.putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE, mock(NetworkTemplate.class));
-        args.putInt(DataUsageList.EXTRA_SUB_ID, 3);
-        mDataUsageList.setArguments(args);
-
-        mDataUsageList.processArgument();
-
-        assertThat(mDataUsageList.mTemplate).isNotNull();
-        assertThat(mDataUsageList.mSubId).isEqualTo(3);
-    }
-
-    @Test
-    public void processArgument_fromIntent_shouldGetTemplateFromIntent() {
-        final Intent intent = new Intent();
-        intent.putExtra(Settings.EXTRA_NETWORK_TEMPLATE, mock(NetworkTemplate.class));
-        intent.putExtra(Settings.EXTRA_SUB_ID, 3);
-        doReturn(intent).when(mDataUsageList).getIntent();
-
-        mDataUsageList.processArgument();
-
-        assertThat(mDataUsageList.mTemplate).isNotNull();
-        assertThat(mDataUsageList.mSubId).isEqualTo(3);
-    }
-
-    @Test
-    public void onLoadFinished_networkCycleDataCallback_shouldShowCycleSpinner() {
-        mDataUsageList.mTemplate = mock(NetworkTemplate.class);
-        mDataUsageList.onCreate(null);
-        mDataUsageList.updatePolicy();
-        List<NetworkCycleChartData> mockData = Collections.emptyList();
-
-        mDataUsageList.mNetworkCycleDataCallbacks.onLoadFinished(null, mockData);
-
-        verify(mDataUsageListHeaderController).updateCycleData(mockData);
-        verify(mDataUsageListHeaderController).setConfigButtonVisible(true);
-    }
-
-    @Test
-    public void onPause_shouldDestroyLoaders() {
-        mDataUsageList.onPause();
-
-        verify(mLoaderManager).destroyLoader(DataUsageList.LOADER_CHART_DATA);
-    }
-
-    @Implements(DataUsageBaseFragment.class)
-    public static class ShadowDataUsageBaseFragment {
-        @Implementation
-        public void onCreate(Bundle icicle) {
-            // do nothing
-        }
-    }
-
-    public class TestDataUsageList extends DataUsageList {
-        @Override
-        protected <T extends AbstractPreferenceController> T use(Class<T> clazz) {
-            return mock(clazz);
-        }
-
-        @Override
-        public <T extends Preference> T findPreference(CharSequence key) {
-            if (key.toString().equals("chart_data")) {
-                return (T) mock(ChartDataUsagePreference.class);
-            }
-            return (T) mock(Preference.class);
-        }
-
-        @Override
-        public Intent getIntent() {
-            return new Intent();
-        }
-
-        @NonNull
-        @Override
-        BillingCycleRepository createBillingCycleRepository() {
-            return mBillingCycleRepository;
-        }
-
-        @Override
-        boolean isBillingCycleModifiable() {
-            return true;
-        }
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.kt b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.kt
new file mode 100644
index 0000000..90bb048
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.kt
@@ -0,0 +1,216 @@
+/*
+ * 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.datausage
+
+import android.content.Context
+import android.content.Intent
+import android.net.NetworkTemplate
+import android.os.Bundle
+import android.os.UserManager
+import android.provider.Settings
+import androidx.preference.Preference
+import androidx.preference.PreferenceManager
+import androidx.test.core.app.ApplicationProvider
+import com.android.settings.datausage.DataUsageListTest.ShadowDataUsageBaseFragment
+import com.android.settings.datausage.TemplatePreference.NetworkServices
+import com.android.settings.datausage.lib.BillingCycleRepository
+import com.android.settings.network.MobileDataEnabledListener
+import com.android.settings.testutils.FakeFeatureFactory
+import com.android.settingslib.NetworkPolicyEditor
+import com.android.settingslib.core.AbstractPreferenceController
+import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers
+import org.mockito.Mock
+import org.mockito.Mockito.doNothing
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
+import org.mockito.Spy
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.Implementation
+import org.robolectric.annotation.Implements
+import org.robolectric.util.ReflectionHelpers
+
+@RunWith(RobolectricTestRunner::class)
+@Config(shadows = [ShadowDataUsageBaseFragment::class])
+class DataUsageListTest {
+    @get:Rule
+    val mockito: MockitoRule = MockitoJUnit.rule()
+
+    @Mock
+    private lateinit var mobileDataEnabledListener: MobileDataEnabledListener
+
+    @Mock
+    private lateinit var networkServices: NetworkServices
+
+    @Mock
+    private lateinit var userManager: UserManager
+
+    @Mock
+    private lateinit var billingCycleRepository: BillingCycleRepository
+
+    @Mock
+    private lateinit var dataUsageListHeaderController: DataUsageListHeaderController
+
+    @Spy
+    private val context: Context = ApplicationProvider.getApplicationContext()
+
+    @Spy
+    private val dataUsageList = TestDataUsageList()
+
+    @Before
+    fun setUp() {
+        FakeFeatureFactory.setupForTest()
+        networkServices.mPolicyEditor = mock(NetworkPolicyEditor::class.java)
+        dataUsageList.dataStateListener = mobileDataEnabledListener
+        doReturn(context).`when`(dataUsageList).context
+        doReturn(userManager).`when`(context).getSystemService(UserManager::class.java)
+        doReturn(false).`when`(userManager).isGuestUser
+        ReflectionHelpers.setField(dataUsageList, "services", networkServices)
+        doNothing().`when`(dataUsageList).updateSubscriptionInfoEntity()
+        `when`(billingCycleRepository.isBandwidthControlEnabled()).thenReturn(true)
+        dataUsageList.dataUsageListHeaderController = dataUsageListHeaderController
+    }
+
+    @Test
+    fun onCreate_isNotGuestUser_shouldNotFinish() {
+        dataUsageList.template = mock<NetworkTemplate>(NetworkTemplate::class.java)
+        doReturn(false).`when`(userManager).isGuestUser
+        doNothing().`when`(dataUsageList).processArgument()
+        dataUsageList.onCreate(null)
+        verify(dataUsageList, never()).finish()
+    }
+
+    @Test
+    fun onCreate_isGuestUser_shouldFinish() {
+        doReturn(true).`when`(userManager).isGuestUser
+        dataUsageList.onCreate(null)
+        verify(dataUsageList).finish()
+    }
+
+    @Test
+    fun resume_shouldListenDataStateChange() {
+        dataUsageList.template = mock(NetworkTemplate::class.java)
+        dataUsageList.onCreate(null)
+        dataUsageList.dataStateListener = mobileDataEnabledListener
+        ReflectionHelpers.setField(
+            dataUsageList,
+            "mVisibilityLoggerMixin",
+            mock(VisibilityLoggerMixin::class.java),
+        )
+        ReflectionHelpers.setField(
+            dataUsageList,
+            "mPreferenceManager",
+            mock(PreferenceManager::class.java),
+        )
+        dataUsageList.onResume()
+        verify(mobileDataEnabledListener).start(ArgumentMatchers.anyInt())
+        dataUsageList.onPause()
+    }
+
+    @Test
+    fun pause_shouldUnlistenDataStateChange() {
+        dataUsageList.template = mock(NetworkTemplate::class.java)
+        dataUsageList.onCreate(null)
+        dataUsageList.dataStateListener = mobileDataEnabledListener
+        ReflectionHelpers.setField(
+            dataUsageList, "mVisibilityLoggerMixin", mock(
+                VisibilityLoggerMixin::class.java
+            )
+        )
+        ReflectionHelpers.setField(
+            dataUsageList, "mPreferenceManager", mock(
+                PreferenceManager::class.java
+            )
+        )
+        dataUsageList.onResume()
+        dataUsageList.onPause()
+        verify(mobileDataEnabledListener).stop()
+    }
+
+    @Test
+    fun processArgument_shouldGetTemplateFromArgument() {
+        val args = Bundle()
+        args.putParcelable(
+            DataUsageList.EXTRA_NETWORK_TEMPLATE, mock(
+                NetworkTemplate::class.java
+            )
+        )
+        args.putInt(DataUsageList.EXTRA_SUB_ID, 3)
+        dataUsageList.arguments = args
+        dataUsageList.processArgument()
+        assertThat(dataUsageList.template).isNotNull()
+        assertThat(dataUsageList.subId).isEqualTo(3)
+    }
+
+    @Test
+    fun processArgument_fromIntent_shouldGetTemplateFromIntent() {
+        val intent = Intent()
+        intent.putExtra(
+            Settings.EXTRA_NETWORK_TEMPLATE, mock(
+                NetworkTemplate::class.java
+            )
+        )
+        intent.putExtra(Settings.EXTRA_SUB_ID, 3)
+        doReturn(intent).`when`(dataUsageList).intent
+        dataUsageList.processArgument()
+        assertThat(dataUsageList.template).isNotNull()
+        assertThat(dataUsageList.subId).isEqualTo(3)
+    }
+
+    @Test
+    fun updatePolicy_setConfigButtonVisible() {
+        dataUsageList.template = mock(NetworkTemplate::class.java)
+        dataUsageList.onCreate(null)
+
+        dataUsageList.updatePolicy()
+
+        verify(dataUsageListHeaderController).setConfigButtonVisible(true)
+    }
+
+    @Implements(DataUsageBaseFragment::class)
+    class ShadowDataUsageBaseFragment {
+        @Implementation
+        fun onCreate(@Suppress("UNUSED_PARAMETER") icicle: Bundle?) {
+            // do nothing
+        }
+    }
+
+    open inner class TestDataUsageList : DataUsageList() {
+        override fun <T : AbstractPreferenceController?> use(clazz: Class<T>): T = mock(clazz)
+
+        @Suppress("UNCHECKED_CAST")
+        override fun <T : Preference?> findPreference(key: CharSequence): T =
+            mock(Preference::class.java) as T
+
+        public override fun getIntent() = Intent()
+
+        override fun createBillingCycleRepository() = billingCycleRepository
+
+        override fun isBillingCycleModifiable() = true
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/datetime/TimePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/TimePreferenceControllerTest.java
index 3481f80..ebb56f4 100644
--- a/tests/robotests/src/com/android/settings/datetime/TimePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/datetime/TimePreferenceControllerTest.java
@@ -36,7 +36,6 @@
 @RunWith(RobolectricTestRunner.class)
 public class TimePreferenceControllerTest {
 
-    @Mock
     private Context mContext;
     @Mock
     private TimePreferenceController.TimePreferenceHost mHost;
@@ -49,6 +48,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
         mPreference = new RestrictedPreference(RuntimeEnvironment.application);
         mController = new TimePreferenceController(mContext, mHost, mDatePreferenceController);
     }
diff --git a/tests/robotests/src/com/android/settings/development/RebootWithMtePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/RebootWithMtePreferenceControllerTest.java
index f1e7d3f..eec7a7b 100644
--- a/tests/robotests/src/com/android/settings/development/RebootWithMtePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/RebootWithMtePreferenceControllerTest.java
@@ -26,6 +26,8 @@
 import androidx.preference.Preference;
 import androidx.test.core.app.ApplicationProvider;
 
+import com.android.settingslib.development.DevelopmentSettingsEnabler;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -52,6 +54,7 @@
         mContext = ApplicationProvider.getApplicationContext();
         mController = new RebootWithMtePreferenceController(mContext);
         mController.setFragment(mFragment);
+        DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(mContext, true);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerTest.java b/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerTest.java
index a338de3..686df7a 100644
--- a/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerTest.java
@@ -17,6 +17,7 @@
 package com.android.settings.development.graphicsdriver;
 
 import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngleAsSystemDriverController.ANGLE_DRIVER_SUFFIX;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngleAsSystemDriverController.PROPERTY_DEBUG_ANGLE_DEVELOPER_OPTION;
 import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngleAsSystemDriverController.PROPERTY_PERSISTENT_GRAPHICS_EGL;
 import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngleAsSystemDriverController.PROPERTY_RO_GFX_ANGLE_SUPPORTED;
 
@@ -71,6 +72,7 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
+        ShadowSystemProperties.override(PROPERTY_DEBUG_ANGLE_DEVELOPER_OPTION, "true");
         doReturn(mTransaction).when(mFragmentManager).beginTransaction();
         doReturn(mFragmentManager).when(mActivity).getSupportFragmentManager();
         doReturn(mActivity).when(mFragment).getActivity();
diff --git a/tests/robotests/src/com/android/settings/display/AutoRotatePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/AutoRotatePreferenceControllerTest.java
index 2bcf060..fd91867 100644
--- a/tests/robotests/src/com/android/settings/display/AutoRotatePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/AutoRotatePreferenceControllerTest.java
@@ -190,15 +190,17 @@
     private void enableAutoRotationPreference() {
         when(mPackageManager.hasSystemFeature(anyString())).thenReturn(true);
         when(mContext.getResources().getBoolean(anyInt())).thenReturn(true);
-        Settings.System.putInt(mContentResolver,
-                Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0);
+        Settings.System.putIntForUser(mContentResolver,
+                Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0,
+                UserHandle.USER_CURRENT);
     }
 
     private void disableAutoRotationPreference() {
         when(mPackageManager.hasSystemFeature(anyString())).thenReturn(true);
         when(mContext.getResources().getBoolean(anyInt())).thenReturn(true);
-        Settings.System.putInt(mContentResolver,
-                Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 1);
+        Settings.System.putIntForUser(mContentResolver,
+                Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 1,
+                UserHandle.USER_CURRENT);
     }
 
     private void enableAutoRotation() {
diff --git a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java
index 0e7a86f..9f1b5d4 100644
--- a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java
@@ -42,6 +42,7 @@
 import com.android.settings.testutils.ResolveInfoBuilder;
 import com.android.settings.testutils.shadow.ShadowDeviceStateRotationLockSettingsManager;
 import com.android.settings.testutils.shadow.ShadowSensorPrivacyManager;
+import com.android.settings.testutils.shadow.ShadowSystemSettings;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -55,6 +56,7 @@
 
 @RunWith(RobolectricTestRunner.class)
 @Config(shadows = {
+        ShadowSystemSettings.class,
         ShadowSensorPrivacyManager.class,
         ShadowDeviceStateRotationLockSettingsManager.class
 })
@@ -234,15 +236,17 @@
     private void enableAutoRotationPreference() {
         when(mPackageManager.hasSystemFeature(anyString())).thenReturn(true);
         when(mResources.getBoolean(anyInt())).thenReturn(true);
-        Settings.System.putInt(mContentResolver,
-                Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0);
+        Settings.System.putIntForUser(mContentResolver,
+                Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0,
+                UserHandle.USER_CURRENT);
     }
 
     private void disableAutoRotationPreference() {
         when(mPackageManager.hasSystemFeature(anyString())).thenReturn(true);
         when(mResources.getBoolean(anyInt())).thenReturn(true);
-        Settings.System.putInt(mContentResolver,
-                Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 1);
+        Settings.System.putIntForUser(mContentResolver,
+                Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 1,
+                UserHandle.USER_CURRENT);
     }
 
     private void enableAutoRotation() {
diff --git a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceFragmentTest.java
index bdff55e..3fa4582 100644
--- a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceFragmentTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.display;
 
+import static android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_LOCKED;
+
 import static com.android.settings.display.SmartAutoRotatePreferenceFragment.AUTO_ROTATE_MAIN_SWITCH_PREFERENCE_KEY;
 import static com.android.settings.display.SmartAutoRotatePreferenceFragment.AUTO_ROTATE_SWITCH_PREFERENCE_KEY;
 
@@ -68,6 +70,11 @@
 })
 public class SmartAutoRotatePreferenceFragmentTest {
 
+    private static final int STATE_FOLDED = 0;
+    private static final int STATE_HALF_FOLDED = 1;
+    private static final int STATE_UNFOLDED = 2;
+    private static final int STATE_REAR_DISPLAY = 3;
+
     private static final String PACKAGE_NAME = "package_name";
 
     private SmartAutoRotatePreferenceFragment mFragment;
@@ -97,6 +104,7 @@
         ContentResolver mContentResolver = RuntimeEnvironment.application.getContentResolver();
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         when(mContext.getContentResolver()).thenReturn(mContentResolver);
+        when(mContext.getApplicationContext()).thenReturn(mContext);
         doReturn(PACKAGE_NAME).when(mPackageManager).getRotationResolverPackageName();
         doReturn(PackageManager.PERMISSION_GRANTED).when(mPackageManager).checkPermission(
                 Manifest.permission.CAMERA, PACKAGE_NAME);
@@ -119,12 +127,19 @@
         when(mFragment.findPreference(AUTO_ROTATE_SWITCH_PREFERENCE_KEY)).thenReturn(
                 mRotateSwitchPreference);
 
+        when(mFragment.findPreference(AUTO_ROTATE_MAIN_SWITCH_PREFERENCE_KEY))
+                .thenReturn(mRotateMainSwitchPreference);
 
-        when(mFragment.findPreference(AUTO_ROTATE_MAIN_SWITCH_PREFERENCE_KEY)).thenReturn(
-                mRotateMainSwitchPreference);
+        when(mResources.getIntArray(com.android.internal.R.array.config_foldedDeviceStates))
+                .thenReturn(new int[] {STATE_FOLDED});
+        when(mResources.getIntArray(com.android.internal.R.array.config_halfFoldedDeviceStates))
+                .thenReturn(new int[] {STATE_HALF_FOLDED});
+        when(mResources.getIntArray(com.android.internal.R.array.config_openDeviceStates))
+                .thenReturn(new int[] {STATE_UNFOLDED});
+        when(mResources.getIntArray(com.android.internal.R.array.config_rearDisplayDeviceStates))
+                .thenReturn(new int[] {STATE_REAR_DISPLAY});
     }
 
-
     @Test
     public void createHeader_faceDetectionSupported_switchBarIsEnabled() {
         ShadowDeviceStateRotationLockSettingsManager.setDeviceStateRotationLockEnabled(false);
@@ -168,7 +183,7 @@
 
     @Test
     public void createPreferenceControllers_noSettableDeviceStates_returnsEmptyList() {
-        enableDeviceStateSettableRotationStates(new String[]{}, new String[]{});
+        enableDeviceStateSettableRotationStates(new String[] {}, new String[] {});
 
         List<AbstractPreferenceController> preferenceControllers =
                 mFragment.createPreferenceControllers(mContext);
@@ -178,17 +193,21 @@
 
     @Test
     public void createPreferenceControllers_settableDeviceStates_returnsDeviceStateControllers() {
-        enableDeviceStateSettableRotationStates(new String[]{"0:1", "1:1"},
-                new String[]{"Folded", "Unfolded"});
+        enableDeviceStateSettableRotationStates(
+                new String[] {
+                    STATE_FOLDED + ":" + DEVICE_STATE_ROTATION_LOCK_LOCKED,
+                    STATE_UNFOLDED + ":" + DEVICE_STATE_ROTATION_LOCK_LOCKED
+                },
+                new String[] {"Folded", "Unfolded"});
 
         List<AbstractPreferenceController> preferenceControllers =
                 mFragment.createPreferenceControllers(mContext);
 
         assertThat(preferenceControllers).hasSize(2);
-        assertThat(preferenceControllers.get(0)).isInstanceOf(
-                DeviceStateAutoRotateSettingController.class);
-        assertThat(preferenceControllers.get(1)).isInstanceOf(
-                DeviceStateAutoRotateSettingController.class);
+        assertThat(preferenceControllers.get(0))
+                .isInstanceOf(DeviceStateAutoRotateSettingController.class);
+        assertThat(preferenceControllers.get(1))
+                .isInstanceOf(DeviceStateAutoRotateSettingController.class);
     }
 
     @Test
@@ -204,16 +223,15 @@
         verify(mFragment, times(1)).addHelpLink();
     }
 
-    private void enableDeviceStateSettableRotationStates(String[] settableStates,
-            String[] settableStatesDescriptions) {
+    private void enableDeviceStateSettableRotationStates(
+            String[] settableStates, String[] settableStatesDescriptions) {
         when(mResources.getStringArray(
-                com.android.internal.R.array.config_perDeviceStateRotationLockDefaults)).thenReturn(
-                settableStates);
-        when(mResources.getStringArray(
-                R.array.config_settableAutoRotationDeviceStatesDescriptions)).thenReturn(
-                settableStatesDescriptions);
-        when(mResources.getBoolean(R.bool.config_auto_rotate_face_detection_available)).thenReturn(
-                true);
+                        com.android.internal.R.array.config_perDeviceStateRotationLockDefaults))
+                .thenReturn(settableStates);
+        when(mResources.getStringArray(R.array.config_settableAutoRotationDeviceStatesDescriptions))
+                .thenReturn(settableStatesDescriptions);
+        when(mResources.getBoolean(R.bool.config_auto_rotate_face_detection_available))
+                .thenReturn(true);
         DeviceStateRotationLockSettingsManager.resetInstance();
         DeviceStateRotationLockSettingsManager.getInstance(mContext)
                 .resetStateForTesting(mResources);
diff --git a/tests/robotests/src/com/android/settings/gestures/GlobalActionsPanelPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/GlobalActionsPanelPreferenceControllerTest.java
deleted file mode 100644
index 65f7ac7..0000000
--- a/tests/robotests/src/com/android/settings/gestures/GlobalActionsPanelPreferenceControllerTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2019 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.gestures;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.provider.Settings;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class GlobalActionsPanelPreferenceControllerTest {
-
-    private Context mContext;
-    private GlobalActionsPanelPreferenceController mController;
-
-    private static final String KEY_GESTURE_PANEL = "gesture_global_actions_panel";
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-        mController = new GlobalActionsPanelPreferenceController(mContext, KEY_GESTURE_PANEL);
-    }
-
-    @Test
-    public void testIsChecked_panelEnabled() {
-        Settings.Secure.putInt(
-                mContext.getContentResolver(), mController.ENABLED_SETTING, 1);
-        assertThat(mController.isChecked()).isTrue();
-    }
-
-    @Test
-    public void testIsChecked_panelDisabled() {
-        Settings.Secure.putInt(
-                mContext.getContentResolver(), mController.ENABLED_SETTING, 0);
-        assertThat(mController.isChecked()).isFalse();
-    }
-
-    @Test
-    public void getAvailabilityStatus_panelAvailable() {
-        Settings.Secure.putInt(
-                mContext.getContentResolver(), mController.AVAILABLE_SETTING, 1);
-        assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.AVAILABLE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_panelUnavailable() {
-        Settings.Secure.putInt(
-                mContext.getContentResolver(), mController.AVAILABLE_SETTING, 0);
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(mController.CONDITIONALLY_UNAVAILABLE);
-    }
-
-    @Test
-    public void isSliceable_correctKey() {
-        final GlobalActionsPanelPreferenceController controller =
-                new GlobalActionsPanelPreferenceController(mContext, mController.TOGGLE_KEY);
-        assertThat(controller.isSliceable()).isTrue();
-    }
-
-    @Test
-    public void isSliceable_incorrectKey() {
-        final GlobalActionsPanelPreferenceController controller =
-                new GlobalActionsPanelPreferenceController(mContext, "bad_key");
-        assertThat(controller.isSliceable()).isFalse();
-    }
-
-    @Test
-    public void isPublicSlice_returnTrue() {
-        assertThat(mController.isPublicSlice()).isTrue();
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
index fceb79d..0909675 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
@@ -145,7 +145,7 @@
     @Test
     public void getCardCount_hasConfiguredCardCount_returnConfiguredCardCount() {
         int configCount = 4;
-        Settings.Global.putLong(mContext.getContentResolver(),
+        Settings.Global.putInt(mContext.getContentResolver(),
                 ContextualCardLoader.CONTEXTUAL_CARD_COUNT, configCount);
 
         assertThat(mContextualCardLoader.getCardCount()).isEqualTo(configCount);
diff --git a/tests/robotests/src/com/android/settings/inputmethod/InputMethodAndSubtypePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/InputMethodAndSubtypePreferenceControllerTest.java
index 26cdd0a..0d1f683 100644
--- a/tests/robotests/src/com/android/settings/inputmethod/InputMethodAndSubtypePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/inputmethod/InputMethodAndSubtypePreferenceControllerTest.java
@@ -47,7 +47,10 @@
 import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
-@Config(shadows = ShadowInputMethodManagerWithMethodList.class)
+@Config(shadows = {
+        ShadowInputMethodManagerWithMethodList.class,
+        com.android.settings.testutils.shadow.ShadowFragment.class,
+})
 public class InputMethodAndSubtypePreferenceControllerTest {
 
     @Mock
diff --git a/tests/robotests/src/com/android/settings/inputmethod/KeyboardLayoutPickerControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/KeyboardLayoutPickerControllerTest.java
index 734f610..0a1ccbb 100644
--- a/tests/robotests/src/com/android/settings/inputmethod/KeyboardLayoutPickerControllerTest.java
+++ b/tests/robotests/src/com/android/settings/inputmethod/KeyboardLayoutPickerControllerTest.java
@@ -50,6 +50,9 @@
 import org.robolectric.shadows.ShadowApplication;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
+        com.android.settings.testutils.shadow.ShadowFragment.class,
+})
 public class KeyboardLayoutPickerControllerTest {
 
     @Mock
diff --git a/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java
index e414929..5fb2d31 100644
--- a/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java
@@ -91,26 +91,6 @@
         assertThat(mController.isAvailable()).isFalse();
     }
 
-    /**
-     * Devices that are not voice capable should still show Ring volume, because it is used by apps
-     * that make calls outside the cell network.
-     */
-    @Test
-    public void isAvailable_notSingleVolume_notVoiceCapable_shouldReturnTrue() {
-        when(mHelper.isSingleVolume()).thenReturn(false);
-        when(mTelephonyManager.isVoiceCapable()).thenReturn(false);
-
-        assertThat(mController.isAvailable()).isTrue();
-    }
-
-    @Test
-    public void isAvailable_notSingleVolume_VoiceCapable_shouldReturnTrue() {
-        when(mHelper.isSingleVolume()).thenReturn(false);
-        when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
-
-        assertThat(mController.isAvailable()).isTrue();
-    }
-
     @Test
     public void getAudioStream_shouldReturnRing() {
         assertThat(mController.getAudioStream()).isEqualTo(AudioManager.STREAM_RING);
diff --git a/tests/robotests/src/com/android/settings/password/ConfirmCredentialTest.java b/tests/robotests/src/com/android/settings/password/ConfirmCredentialTest.java
index 299b1eb..92b2b62 100644
--- a/tests/robotests/src/com/android/settings/password/ConfirmCredentialTest.java
+++ b/tests/robotests/src/com/android/settings/password/ConfirmCredentialTest.java
@@ -47,6 +47,7 @@
 import com.android.settings.testutils.shadow.ShadowUtils;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.MockitoAnnotations;
@@ -128,6 +129,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void onCreate_remoteValidation_invalidServiceComponentName_finishActivity()
             throws Exception {
         Intent intentWithInvalidComponentName = new Intent()
diff --git a/tests/robotests/src/com/android/settings/password/ConfirmLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/ConfirmLockPasswordTest.java
index d26c33b..4ac375f 100644
--- a/tests/robotests/src/com/android/settings/password/ConfirmLockPasswordTest.java
+++ b/tests/robotests/src/com/android/settings/password/ConfirmLockPasswordTest.java
@@ -62,6 +62,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -176,6 +177,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void handleNext_remoteValidation_correctGuess_checkboxChecked() throws Exception {
         ConfirmDeviceCredentialBaseActivity activity =
                 buildConfirmDeviceCredentialBaseActivity(
@@ -201,6 +203,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void handleNext_remoteValidation_correctGuess_checkboxUnchecked() throws Exception {
         ConfirmDeviceCredentialBaseActivity activity =
                 buildConfirmDeviceCredentialBaseActivity(
@@ -227,6 +230,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void handleNext_remoteValidation_guessInvalid() throws Exception {
         ConfirmDeviceCredentialBaseActivity activity =
                 buildConfirmDeviceCredentialBaseActivity(
@@ -251,6 +255,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void handleNext_remoteValidation_lockout() throws Exception {
         ConfirmDeviceCredentialBaseActivity activity =
                 buildConfirmDeviceCredentialBaseActivity(
@@ -275,6 +280,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void handleNext_remoteValidation_noRemainingAttempts_finishActivity() throws Exception {
         ConfirmDeviceCredentialBaseActivity activity =
                 buildConfirmDeviceCredentialBaseActivity(
diff --git a/tests/robotests/src/com/android/settings/password/ConfirmLockPatternTest.java b/tests/robotests/src/com/android/settings/password/ConfirmLockPatternTest.java
index 2ed7988..04a76b8 100644
--- a/tests/robotests/src/com/android/settings/password/ConfirmLockPatternTest.java
+++ b/tests/robotests/src/com/android/settings/password/ConfirmLockPatternTest.java
@@ -58,6 +58,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -156,6 +157,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void onPatternDetected_remoteValidation_guessValid_checkboxChecked() throws Exception {
         ConfirmDeviceCredentialBaseActivity activity =
                 buildConfirmDeviceCredentialBaseActivity(
@@ -181,6 +183,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void onPatternDetected_remoteValidation_guessValid_checkboxUnchecked() throws Exception {
         ConfirmDeviceCredentialBaseActivity activity =
                 buildConfirmDeviceCredentialBaseActivity(
@@ -207,6 +210,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void onPatternDetected_remoteValidation_guessInvalid() throws Exception {
         ConfirmDeviceCredentialBaseActivity activity =
                 buildConfirmDeviceCredentialBaseActivity(
@@ -231,6 +235,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void onPatternDetected_remoteValidation_lockout() throws Exception {
         ConfirmDeviceCredentialBaseActivity activity =
                 buildConfirmDeviceCredentialBaseActivity(
@@ -255,6 +260,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void onPatternDetected_noRemainingAttempts_finishActivity() throws Exception {
         ConfirmDeviceCredentialBaseActivity activity =
                 buildConfirmDeviceCredentialBaseActivity(
diff --git a/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java b/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java
index af44d39..5e429d9 100644
--- a/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetNewPasswordActivityTest.java
@@ -50,6 +50,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -90,6 +91,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void testChooseLockGeneric() {
         Settings.Global.putInt(RuntimeEnvironment.application.getContentResolver(),
                 Settings.Global.DEVICE_PROVISIONED, 1);
diff --git a/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
index 97a326f..e207d24 100644
--- a/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
@@ -47,6 +47,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
@@ -122,6 +123,7 @@
 
     @Test
     @Config(shadows = ShadowChooseLockGenericController.class)
+    @Ignore("b/295325503")
     public void createActivity_withShowOptionsButtonExtra_buttonNotVisibleIfNoVisibleLockTypes() {
         SetupChooseLockPassword activity = createSetupChooseLockPassword();
         Button optionsButton = activity.findViewById(R.id.screen_lock_options);
diff --git a/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java b/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
index 648c42f..7767644 100644
--- a/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
@@ -51,6 +51,7 @@
 import com.google.android.setupcompat.template.FooterButton;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
@@ -99,6 +100,7 @@
     }
 
     @Test
+    @Ignore("b/295325503")
     public void optionsButton_whenPatternSelected_shouldBeVisible() {
         final Button button = mActivity.findViewById(R.id.screen_lock_options);
         assertThat(button).isNotNull();
@@ -125,12 +127,14 @@
 
     @Config(qualifiers = "sw400dp")
     @Test
+    @Ignore("b/295325503")
     public void sw400dp_shouldShowScreenLockOptions() {
         verifyScreenLockOptionsShown();
     }
 
     @Config(qualifiers = "sw400dp-land")
     @Test
+    @Ignore("b/295325503")
     public void sw400dpLandscape_shouldShowScreenLockOptions() {
         verifyScreenLockOptionsShown();
     }
@@ -143,17 +147,20 @@
 
     @Config(qualifiers = "sw300dp")
     @Test
+    @Ignore("b/295325503")
     public void smallScreens_shouldHideScreenLockOptions() {
         verifyScreenLockOptionsHidden();
     }
 
     @Config(qualifiers = "sw300dp-land")
     @Test
+    @Ignore("b/295325503")
     public void smallScreensLandscape_shouldHideScreenLockOptions() {
         verifyScreenLockOptionsHidden();
     }
 
     @Test
+    @Ignore("b/295325503")
     public void skipButton_shouldBeVisible_duringNonFingerprintFlow() {
         final PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
         final Button skipOrClearButton =
diff --git a/tests/robotests/src/com/android/settings/search/SettingsSearchIndexablesProviderTest.java b/tests/robotests/src/com/android/settings/search/SettingsSearchIndexablesProviderTest.java
index 21b00a3..5de64b5 100644
--- a/tests/robotests/src/com/android/settings/search/SettingsSearchIndexablesProviderTest.java
+++ b/tests/robotests/src/com/android/settings/search/SettingsSearchIndexablesProviderTest.java
@@ -1,5 +1,6 @@
 package com.android.settings.search;
 
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SEARCHABLE;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -205,6 +206,19 @@
         assertThat(mProvider.isEligibleForIndexing(PACKAGE_NAME, activityTile)).isTrue();
     }
 
+    @Test
+    public void isEligibleForIndexing_disabledByMetadata_shouldReturnFalse() {
+        final ActivityInfo activityInfo = new ActivityInfo();
+        activityInfo.packageName = PACKAGE_NAME;
+        activityInfo.name = "class";
+        activityInfo.metaData = new Bundle();
+        activityInfo.metaData.putBoolean(META_DATA_PREFERENCE_SEARCHABLE, false);
+        final ActivityTile activityTile = new ActivityTile(activityInfo,
+                CategoryKey.CATEGORY_CONNECT);
+
+        assertThat(mProvider.isEligibleForIndexing(PACKAGE_NAME, activityTile)).isFalse();
+    }
+
     @Implements(CategoryManager.class)
     public static class ShadowCategoryManager {
 
diff --git a/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java b/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java
index e1b2b4e..cbdcf3c 100644
--- a/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java
+++ b/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java
@@ -30,7 +30,6 @@
 
 import static com.android.settings.sim.SimDialogActivity.DATA_PICK;
 import static com.android.settings.sim.SimDialogActivity.INVALID_PICK;
-import static com.android.settings.sim.SimDialogActivity.PICK_DISMISS;
 import static com.android.settings.sim.SimSelectNotification.ENABLE_MMS_NOTIFICATION_CHANNEL;
 import static com.android.settings.sim.SimSelectNotification.ENABLE_MMS_NOTIFICATION_ID;
 import static com.android.settings.sim.SimSelectNotification.SIM_WARNING_NOTIFICATION_CHANNEL;
@@ -61,6 +60,8 @@
 import android.telephony.TelephonyManager;
 import android.util.DisplayMetrics;
 
+import androidx.test.core.app.ApplicationProvider;
+
 import com.android.settings.R;
 import com.android.settings.network.SubscriptionUtil;
 import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
@@ -71,6 +72,7 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.Config;
 
@@ -80,8 +82,8 @@
 @RunWith(RobolectricTestRunner.class)
 @Config(shadows = ShadowAlertDialogCompat.class)
 public class SimSelectNotificationTest {
-    @Mock
-    private Context mContext;
+    @Spy
+    private Context mContext = ApplicationProvider.getApplicationContext();
     @Mock
     private Executor mExecutor;
     @Mock
@@ -92,8 +94,8 @@
     private SubscriptionManager mSubscriptionManager;
     @Mock
     private PackageManager mPackageManager;
-    @Mock
-    private Resources mResources;
+    @Spy
+    private Resources mResources = mContext.getResources();
     @Mock
     private SubscriptionInfo mSubInfo;
     @Mock
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRotationPolicy.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRotationPolicy.java
index 1f1e2be..d052340 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRotationPolicy.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRotationPolicy.java
@@ -30,12 +30,13 @@
     private static boolean rotationSupported = true;
 
     @Implementation
-    protected static void setRotationLock(Context context, final boolean enabled) {
+    protected static void setRotationLock(Context context, final boolean enabled, String caller) {
         rotationLockEnabled = enabled;
     }
 
     @Implementation
-    protected static void setRotationLockForAccessibility(Context context, final boolean enabled) {
+    protected static void setRotationLockForAccessibility(
+            Context context, final boolean enabled, String caller) {
         rotationLockEnabled = enabled;
     }
 
diff --git a/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java b/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java
index 256e08b..b339052 100644
--- a/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java
@@ -80,7 +80,8 @@
 
 @RunWith(RobolectricTestRunner.class)
 @Config(shadows = {
-        // ShadowUserManager.class,
+        ShadowUserManager.class,
+        com.android.settings.testutils.shadow.ShadowFragment.class,
         ShadowDevicePolicyManager.class
 })
 public class UserDetailsSettingsTest {
diff --git a/tests/robotests/src/com/android/settings/vpn2/AppDialogFragmentTest.java b/tests/robotests/src/com/android/settings/vpn2/AppDialogFragmentTest.java
index 2b81f16..b13ec6a 100644
--- a/tests/robotests/src/com/android/settings/vpn2/AppDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/vpn2/AppDialogFragmentTest.java
@@ -29,8 +29,13 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
+        com.android.settings.testutils.shadow.ShadowFragment.class,
+})
+
 public class AppDialogFragmentTest {
 
     @Mock
diff --git a/tests/robotests/src/com/android/settings/webview/WebViewAppPickerTest.java b/tests/robotests/src/com/android/settings/webview/WebViewAppPickerTest.java
index bed88e7..c693938 100644
--- a/tests/robotests/src/com/android/settings/webview/WebViewAppPickerTest.java
+++ b/tests/robotests/src/com/android/settings/webview/WebViewAppPickerTest.java
@@ -66,6 +66,7 @@
 @RunWith(RobolectricTestRunner.class)
 @Config(shadows = {
         ShadowUserManager.class,
+        com.android.settings.testutils.shadow.ShadowFragment.class,
 })
 public class WebViewAppPickerTest {
 
diff --git a/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java b/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java
index 06b99a4..9ed6de3 100644
--- a/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java
@@ -52,8 +52,12 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
+        com.android.settings.testutils.shadow.ShadowFragment.class,
+})
 public class EntityHeaderControllerTest {
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
diff --git a/tests/robotests/src/com/android/settings/widget/HighlightablePreferenceGroupAdapterTest.java b/tests/robotests/src/com/android/settings/widget/HighlightablePreferenceGroupAdapterTest.java
index d6d5abf..29560ab 100644
--- a/tests/robotests/src/com/android/settings/widget/HighlightablePreferenceGroupAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/widget/HighlightablePreferenceGroupAdapterTest.java
@@ -53,9 +53,13 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
 import org.robolectric.util.ReflectionHelpers;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
+        com.android.settings.testutils.shadow.ShadowFragment.class,
+})
 public class HighlightablePreferenceGroupAdapterTest {
 
     private static final String TEST_KEY = "key";
diff --git a/tests/robotests/src/com/android/settings/widget/SettingsMainSwitchPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/SettingsMainSwitchPreferenceTest.java
index d64d237..a5ebdad 100644
--- a/tests/robotests/src/com/android/settings/widget/SettingsMainSwitchPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/widget/SettingsMainSwitchPreferenceTest.java
@@ -22,12 +22,9 @@
 
 import android.content.Context;
 import android.view.View;
-import android.widget.ImageView;
 
 import androidx.preference.PreferenceViewHolder;
 
-import com.android.settings.R;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -59,17 +56,6 @@
     }
 
     @Test
-    public void onBindViewHolder_isRestricted_restrictIconShouldDisplay() {
-        mPreference.onBindViewHolder(mHolder);
-
-        final SettingsMainSwitchBar switchBar = mPreference.getSwitchBar();
-        final ImageView restrictedIcon = switchBar.findViewById(
-                com.android.settingslib.widget.restricted.R.id.restricted_icon);
-
-        assertThat(restrictedIcon.getVisibility() == View.VISIBLE).isTrue();
-    }
-
-    @Test
     public void show_preferenceShouldDisplay() {
         mPreference.show();
 
diff --git a/tests/robotests/src/com/android/settings/wifi/ConfigureWifiSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/ConfigureWifiSettingsTest.java
index 5e3d715..5bacfab 100644
--- a/tests/robotests/src/com/android/settings/wifi/ConfigureWifiSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/ConfigureWifiSettingsTest.java
@@ -45,6 +45,9 @@
 import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
+        com.android.settings.testutils.shadow.ShadowFragment.class,
+})
 public class ConfigureWifiSettingsTest {
 
     @Rule
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java b/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java
index c9cc02e..5a39368 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java
@@ -27,7 +27,9 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -42,6 +44,7 @@
 
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settingslib.wifi.AccessPoint;
+import com.android.wifitrackerlib.NetworkDetailsTracker;
 import com.android.wifitrackerlib.WifiEntry;
 
 import com.google.android.setupcompat.util.WizardManagerHelper;
@@ -59,14 +62,13 @@
 
     static final String CALLING_PACKAGE = "calling_package";
     static final int REQUEST_CODE = REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER;
+    private static final String SSID = "SSID";
 
     @Mock
     UserManager mUserManager;
     @Mock
     PackageManager mPackageManager;
     @Mock
-    WifiManager mWifiManager;
-    @Mock
     WifiDialog mWifiDialog;
     @Mock
     WifiConfiguration mWifiConfiguration;
@@ -91,16 +93,22 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         when(mWifiDialog.getController()).thenReturn(mController);
+        mWifiConfiguration.SSID = SSID;
         when(mController.getConfig()).thenReturn(mWifiConfiguration);
         when(mController.getAccessPoint()).thenReturn(mAccessPoint);
         when(mWifiDialog2.getController()).thenReturn(mWifiConfiguration2);
         when(mWifiConfiguration2.getWifiEntry()).thenReturn(mWifiEntry);
         when(mWifiEntry.canConnect()).thenReturn(true);
         FakeFeatureFactory.setupForTest();
+        WifiTrackerLibProvider mockWifiTrackerLibProvider =
+                FakeFeatureFactory.getFeatureFactory().getWifiTrackerLibProvider();
+        when(mockWifiTrackerLibProvider.createNetworkDetailsTracker(
+                any(), any(), any(), any(), any(), anyLong(), anyLong(), any())
+        ).thenReturn(mock(NetworkDetailsTracker.class));
 
         mActivity = spy(Robolectric.setupActivity(WifiDialogActivity.class));
         when(mActivity.getSystemService(UserManager.class)).thenReturn(mUserManager);
-        when(mActivity.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
+
         when(mActivity.getSystemService(KeyguardManager.class)).thenReturn(mKeyguardManager);
     }
 
@@ -108,7 +116,8 @@
     public void onSubmit_shouldConnectToNetwork() {
         mActivity.onSubmit(mWifiDialog);
 
-        verify(mWifiManager).connect(any(), any());
+        WifiManager wifiManager = mActivity.getSystemService(WifiManager.class);
+        assertThat(wifiManager.getConnectionInfo().getSSID()).isEqualTo("\"SSID\"");
     }
 
     @Test
@@ -155,7 +164,6 @@
         intent.putExtra(WifiDialogActivity.KEY_CHOSEN_WIFIENTRY_KEY, "FAKE_KEY");
         intent.putExtra(WifiDialogActivity.KEY_CONNECT_FOR_CALLER, true);
         mActivity = spy(Robolectric.buildActivity(WifiDialogActivity.class, intent).setup().get());
-        when(mActivity.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
 
         mActivity.onSubmit(mWifiDialog2);
 
@@ -167,11 +175,11 @@
         final Intent intent = new Intent();
         intent.putExtra(WifiDialogActivity.KEY_CONNECT_FOR_CALLER, false);
         mActivity = spy(Robolectric.buildActivity(WifiDialogActivity.class, intent).setup().get());
-        when(mActivity.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
 
         mActivity.onSubmit(mWifiDialog);
 
-        verify(mWifiManager, never()).connect(any(), any());
+        WifiManager wifiManager = mActivity.getSystemService(WifiManager.class);
+        assertThat(wifiManager.getConnectionInfo().getSSID()).isEqualTo(WifiManager.UNKNOWN_SSID);
     }
 
     @Test
@@ -180,7 +188,6 @@
         intent.putExtra(WifiDialogActivity.KEY_CHOSEN_WIFIENTRY_KEY, "FAKE_KEY");
         intent.putExtra(WifiDialogActivity.KEY_CONNECT_FOR_CALLER, false);
         mActivity = spy(Robolectric.buildActivity(WifiDialogActivity.class, intent).setup().get());
-        when(mActivity.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
 
         mActivity.onSubmit(mWifiDialog2);
 
@@ -193,8 +200,7 @@
         intent.putExtra(WifiDialogActivity.KEY_CONNECT_FOR_CALLER, false);
         intent.putExtra(WizardManagerHelper.EXTRA_IS_FIRST_RUN, true);
         intent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true);
-        mActivity = spy(Robolectric.buildActivity(WifiDialogActivity.class, intent).setup().get());
-        when(mActivity.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
+        mActivity = spy(Robolectric.buildActivity(WifiDialogActivity.class, intent).create().get());
         doNothing().when(mActivity).createDialogWithSuwTheme();
 
         mActivity.onStart();
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiScanningRequiredFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/WifiScanningRequiredFragmentTest.java
index 6969e14..f732b5e 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiScanningRequiredFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiScanningRequiredFragmentTest.java
@@ -47,8 +47,12 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
+        com.android.settings.testutils.shadow.ShadowFragment.class,
+})
 public class WifiScanningRequiredFragmentTest {
 
     private WifiScanningRequiredFragment mFragment;
diff --git a/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragmentTest.java
index 303963d..699a8e8 100644
--- a/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/addappnetworks/AddAppNetworksFragmentTest.java
@@ -55,12 +55,16 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.Robolectric;
 import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
 import org.robolectric.shadows.androidx.fragment.FragmentController;
 
 import java.util.ArrayList;
 import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
+        com.android.settings.testutils.shadow.ShadowFragment.class,
+})
 public class AddAppNetworksFragmentTest {
 
     private static final String FAKE_APP_NAME = "fake_app_name";
diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
index bcc0933..2d64e16 100644
--- a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java
@@ -47,7 +47,6 @@
 import androidx.slice.widget.SliceContent;
 import androidx.slice.widget.SliceLiveData;
 
-import com.android.ims.ImsManager;
 import com.android.settings.R;
 import com.android.settings.network.ims.MockWifiCallingQueryImsState;
 import com.android.settings.slices.CustomSliceRegistry;
@@ -79,9 +78,6 @@
     private CarrierConfigManager mMockCarrierConfigManager;
 
     @Mock
-    private ImsManager mMockImsManager;
-
-    @Mock
     private ImsMmTelManager mMockImsMmTelManager;
 
     private MockWifiCallingQueryImsState mQueryImsState;
@@ -122,20 +118,7 @@
     }
 
     @Test
-    public void test_CreateWifiCallingSlice_invalidSubId() {
-        mQueryImsState.setIsEnabledByUser(true);
-        mQueryImsState.setIsProvisionedOnDevice(false);
-        mWfcSliceHelper.setDefaultVoiceSubId(-1);
-        mQueryImsState.setIsReadyToWifiCalling(true);
-
-        final Slice slice = mWfcSliceHelper.createWifiCallingSlice(
-                CustomSliceRegistry.WIFI_CALLING_URI);
-
-        assertThat(slice).isNull();
-    }
-
-    @Test
-    public void test_CreateWifiCallingSlice_wfcNotSupported() {
+    public void createWifiCallingSlice_notReadyToWifiCalling_wfcNotSupported() {
         mQueryImsState.setIsProvisionedOnDevice(false);
         mQueryImsState.setIsReadyToWifiCalling(false);
 
diff --git a/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java b/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
index 4b01aaf..11d421c 100644
--- a/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
@@ -120,7 +120,10 @@
 
 // TODO(b/143326832): Should add test cases for connect button.
 @RunWith(RobolectricTestRunner.class)
-@Config(shadows = {ShadowDevicePolicyManager.class, ShadowEntityHeaderController.class})
+@Config(shadows = {
+        ShadowDevicePolicyManager.class,
+        com.android.settings.testutils.shadow.ShadowFragment.class,
+        ShadowEntityHeaderController.class})
 public class WifiDetailPreferenceController2Test {
 
     private static final int LEVEL = 1;
@@ -434,16 +437,6 @@
     }
 
     @Test
-    public void latestWifiInfo_shouldBeFetchedInDisplayPreferenceForConnectedNetwork() {
-        setUpForConnectedNetwork();
-        setUpSpyController();
-
-        displayAndResume();
-
-        verify(mMockWifiManager, times(1)).getConnectionInfo();
-    }
-
-    @Test
     public void latestWifiInfo_shouldNotBeFetchedInDisplayPreferenceForDisconnectedNetwork() {
         setUpForDisconnectedNetwork();
 
@@ -462,16 +455,6 @@
     }
 
     @Test
-    public void latestNetworkInfo_shouldBeFetchedInDisplayPreferenceForConnectedNetwork() {
-        setUpForConnectedNetwork();
-        setUpSpyController();
-
-        displayAndResume();
-
-        verify(mMockConnectivityManager, times(1)).getNetworkInfo(any(Network.class));
-    }
-
-    @Test
     public void latestNetworkInfo_shouldNotBeFetchedInDisplayPreferenceForDisconnectedNetwork() {
         setUpForDisconnectedNetwork();
 
@@ -1280,8 +1263,9 @@
 
         displayAndResume();
 
-        verify(mMockConnectivityManager, times(1)).getNetworkInfo(any(Network.class));
-        verify(mMockWifiManager, times(1)).getConnectionInfo();
+        verify(mMockWifiManager, times(1)).getCurrentNetwork();
+        verify(mMockConnectivityManager, times(1)).getLinkProperties(any(Network.class));
+        verify(mMockConnectivityManager, times(1)).getNetworkCapabilities(any(Network.class));
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
index bf978c7..ff1125d 100644
--- a/tests/robotests/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragmentTest.java
@@ -43,10 +43,14 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
 
 import java.util.Arrays;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
+        com.android.settings.testutils.shadow.ShadowFragment.class,
+})
 public class WifiDppQrCodeScannerFragmentTest {
 
     static final String WIFI_SSID = "wifi-ssid";
diff --git a/tests/robotests/src/com/android/settings/wifi/p2p/WifiP2pSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/p2p/WifiP2pSettingsTest.java
index a8b1d9c..99286cf 100644
--- a/tests/robotests/src/com/android/settings/wifi/p2p/WifiP2pSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/p2p/WifiP2pSettingsTest.java
@@ -51,6 +51,7 @@
 import com.android.settingslib.core.AbstractPreferenceController;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -65,6 +66,7 @@
 
 @RunWith(RobolectricTestRunner.class)
 @Config(shadows = ShadowInteractionJankMonitor.class)
+@Ignore
 public class WifiP2pSettingsTest {
 
     private Context mContext;
diff --git a/tests/shared/Android.bp b/tests/shared/Android.bp
new file mode 100644
index 0000000..fca24b6
--- /dev/null
+++ b/tests/shared/Android.bp
@@ -0,0 +1,9 @@
+android_library {
+    name: "Settings-testutils2",
+    srcs: [
+        "src/**/*.kt"
+    ],
+    libs: [
+        "FingerprintManagerInteractor",
+    ],
+}
diff --git a/tests/shared/AndroidManifest.xml b/tests/shared/AndroidManifest.xml
new file mode 100644
index 0000000..7e1842c
--- /dev/null
+++ b/tests/shared/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.settings.testutils2">
+</manifest>
diff --git a/tests/unit/src/com/android/settings/fingerprint2/domain/interactor/FakeFingerprintManagerInteractor.kt b/tests/shared/src/com/android/settings/testutils2/FakeFingerprintManagerInteractor.kt
similarity index 71%
rename from tests/unit/src/com/android/settings/fingerprint2/domain/interactor/FakeFingerprintManagerInteractor.kt
rename to tests/shared/src/com/android/settings/testutils2/FakeFingerprintManagerInteractor.kt
index f807f70..05c3e3c 100644
--- a/tests/unit/src/com/android/settings/fingerprint2/domain/interactor/FakeFingerprintManagerInteractor.kt
+++ b/tests/shared/src/com/android/settings/testutils2/FakeFingerprintManagerInteractor.kt
@@ -14,18 +14,19 @@
  * limitations under the License.
  */
 
-package com.android.settings.fingerprint2.domain.interactor
+package com.android.settings.testutils2
 
-import android.hardware.biometrics.SensorProperties
-import android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
-import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractor
+import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
 import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptViewModel
+import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintSensorPropertyViewModel
 import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintViewModel
-import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.EnrollReason
-import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerEnrollStateViewModel
+import com.android.settings.biometrics.fingerprint2.shared.model.EnrollReason
+import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollStateViewModel
+import com.android.settings.biometrics.fingerprint2.shared.model.SensorStrength
+import com.android.settings.biometrics.fingerprint2.shared.model.SensorType
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.flowOf
 
 /** Fake to be used by other classes to easily fake the FingerprintManager implementation. */
 class FakeFingerprintManagerInteractor : FingerprintManagerInteractor {
@@ -37,17 +38,8 @@
   val enrollStateViewModel = FingerEnrollStateViewModel.EnrollProgress(1)
   var pressToAuthEnabled = true
 
-  var sensorProps =
-    listOf(
-      FingerprintSensorPropertiesInternal(
-        0 /* sensorId */,
-        SensorProperties.STRENGTH_STRONG,
-        5 /* maxEnrollmentsPerUser */,
-        emptyList() /* ComponentInfoInternal */,
-        TYPE_POWER_BUTTON,
-        true /* resetLockoutRequiresHardwareAuthToken */
-      )
-    )
+  var sensorProp =
+    FingerprintSensorPropertyViewModel(0 /* sensorId */, SensorStrength.Strong, 5, SensorType.SFPS)
 
   override suspend fun authenticate(): FingerprintAuthAttemptViewModel {
     return authenticateAttempt
@@ -65,8 +57,8 @@
     emit(enrolledFingerprintsInternal.size < enrollableFingerprints)
   }
 
-  override val sensorPropertiesInternal: Flow<FingerprintSensorPropertiesInternal?> = flow {
-    emit(sensorProps.first())
+  override val sensorPropertiesInternal: Flow<FingerprintSensorPropertyViewModel?> = flow {
+    emit(sensorProp)
   }
 
   override val maxEnrollableFingerprints: Flow<Int> = flow { emit(enrollableFingerprints) }
@@ -74,7 +66,7 @@
   override suspend fun enroll(
     hardwareAuthToken: ByteArray?,
     enrollReason: EnrollReason
-  ): Flow<FingerEnrollStateViewModel> = flow { emit(enrollStateViewModel) }
+  ): Flow<FingerEnrollStateViewModel> = flowOf(enrollStateViewModel)
 
   override suspend fun removeFingerprint(fp: FingerprintViewModel): Boolean {
     return enrolledFingerprintsInternal.remove(fp)
@@ -87,7 +79,7 @@
   }
 
   override suspend fun hasSideFps(): Boolean {
-    return sensorProps.any { it.isAnySidefpsType }
+    return sensorProp.sensorType == SensorType.SFPS
   }
 
   override suspend fun pressToAuthEnabled(): Boolean {
diff --git a/tests/spa_unit/src/com/android/settings/datausage/ChartDataUsagePreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/datausage/ChartDataUsagePreferenceControllerTest.kt
new file mode 100644
index 0000000..1748f07
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/datausage/ChartDataUsagePreferenceControllerTest.kt
@@ -0,0 +1,83 @@
+/*
+ * 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.datausage
+
+import android.content.Context
+import androidx.lifecycle.testing.TestLifecycleOwner
+import androidx.preference.PreferenceScreen
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.datausage.lib.INetworkCycleDataRepository
+import com.android.settings.datausage.lib.NetworkCycleChartData
+import com.android.settings.datausage.lib.NetworkUsageData
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+
+@RunWith(AndroidJUnit4::class)
+class ChartDataUsagePreferenceControllerTest {
+    private val context: Context = ApplicationProvider.getApplicationContext()
+
+    private val repository = object : INetworkCycleDataRepository {
+        override suspend fun loadCycles() = emptyList<NetworkUsageData>()
+
+        override fun getPolicy() = null
+
+        override suspend fun querySummary(startTime: Long, endTime: Long) = when {
+            startTime == START_TIME && endTime == END_TIME -> CycleChartDate
+            else -> null
+        }
+    }
+
+    private val preference = mock<ChartDataUsagePreference>()
+    private val preferenceScreen = mock<PreferenceScreen> {
+        onGeneric { findPreference(KEY) } doReturn preference
+    }
+
+    private val controller = ChartDataUsagePreferenceController(context, KEY)
+
+    @Before
+    fun setUp() {
+        controller.init(repository)
+        controller.displayPreference(preferenceScreen)
+        controller.onViewCreated(TestLifecycleOwner())
+    }
+
+    @Test
+    fun update() = runBlocking {
+        controller.update(START_TIME, END_TIME)
+        delay(100L)
+
+        verify(preference).setTime(START_TIME, END_TIME)
+        verify(preference).setNetworkCycleData(CycleChartDate)
+    }
+
+    private companion object {
+        const val KEY = "test_key"
+        const val START_TIME = 1L
+        const val END_TIME = 2L
+
+        val UsageData = NetworkUsageData(startTime = START_TIME, endTime = END_TIME, usage = 10)
+        val CycleChartDate =
+            NetworkCycleChartData(total = UsageData, dailyUsage = listOf(UsageData))
+    }
+}
diff --git a/tests/spa_unit/src/com/android/settings/datausage/DataUsageListAppsControllerTest.kt b/tests/spa_unit/src/com/android/settings/datausage/DataUsageListAppsControllerTest.kt
index af5dc89..2646323 100644
--- a/tests/spa_unit/src/com/android/settings/datausage/DataUsageListAppsControllerTest.kt
+++ b/tests/spa_unit/src/com/android/settings/datausage/DataUsageListAppsControllerTest.kt
@@ -22,8 +22,8 @@
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.android.settings.SettingsActivity
+import com.android.settings.datausage.lib.NetworkUsageData
 import com.android.settingslib.AppItem
-import com.android.settingslib.net.NetworkCycleChartData
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Test
@@ -48,11 +48,8 @@
     @Before
     fun setUp() {
         controller.init(mock<NetworkTemplate>())
-        val data = NetworkCycleChartData.Builder().apply {
-            setStartTime(START_TIME)
-            setEndTime(END_TIME)
-        }.build()
-        controller.setCycleData(listOf(data))
+        val data = NetworkUsageData(START_TIME, END_TIME, 0)
+        controller.updateCycles(listOf(data))
     }
 
     @Test
diff --git a/tests/spa_unit/src/com/android/settings/datausage/DataUsageListHeaderControllerTest.kt b/tests/spa_unit/src/com/android/settings/datausage/DataUsageListHeaderControllerTest.kt
index a1eebe7..35b70d6 100644
--- a/tests/spa_unit/src/com/android/settings/datausage/DataUsageListHeaderControllerTest.kt
+++ b/tests/spa_unit/src/com/android/settings/datausage/DataUsageListHeaderControllerTest.kt
@@ -21,10 +21,16 @@
 import android.view.LayoutInflater
 import android.view.View
 import android.widget.Spinner
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.testing.TestLifecycleOwner
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.android.settings.R
+import com.android.settings.datausage.lib.INetworkCycleDataRepository
+import com.android.settings.datausage.lib.NetworkUsageData
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.kotlin.any
@@ -40,6 +46,14 @@
         doNothing().whenever(mock).startActivity(any())
     }
 
+    private val repository = object : INetworkCycleDataRepository {
+        override suspend fun loadCycles() = emptyList<NetworkUsageData>()
+
+        override fun getPolicy() = null
+
+        override suspend fun querySummary(startTime: Long, endTime: Long) = null
+    }
+
     private val header =
         LayoutInflater.from(context).inflate(R.layout.apps_filter_spinner, null, false)
 
@@ -47,11 +61,16 @@
 
     private val spinner: Spinner = header.requireViewById(R.id.filter_spinner)
 
+    private val testLifecycleOwner = TestLifecycleOwner(initialState = Lifecycle.State.CREATED)
+
     private val controller = DataUsageListHeaderController(
         header = header,
         template = mock<NetworkTemplate>(),
         sourceMetricsCategory = 0,
-        onItemSelected = { _, _ -> },
+        viewLifecycleOwner = testLifecycleOwner,
+        onCyclesLoad = {},
+        onItemSelected = {},
+        repository = repository,
     )
 
     @Test
@@ -60,8 +79,9 @@
     }
 
     @Test
-    fun updateCycleData_shouldShowCycleSpinner() {
-        controller.updateCycleData(emptyList())
+    fun updateCycleData_shouldShowCycleSpinner() = runBlocking {
+        testLifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_START)
+        delay(100)
 
         assertThat(spinner.visibility).isEqualTo(View.VISIBLE)
     }
diff --git a/tests/spa_unit/src/com/android/settings/datausage/lib/NetworkCycleDataRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/datausage/lib/NetworkCycleDataRepositoryTest.kt
new file mode 100644
index 0000000..fb5e820
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/datausage/lib/NetworkCycleDataRepositoryTest.kt
@@ -0,0 +1,168 @@
+/*
+ * 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.datausage.lib
+
+import android.app.usage.NetworkStats.Bucket
+import android.app.usage.NetworkStatsManager
+import android.content.Context
+import android.net.NetworkPolicy
+import android.net.NetworkTemplate
+import android.text.format.DateUtils
+import android.util.Range
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import java.time.Instant
+import java.time.ZoneId
+import java.time.ZonedDateTime
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.whenever
+
+@RunWith(AndroidJUnit4::class)
+class NetworkCycleDataRepositoryTest {
+    private val mockNetworkStatsManager = mock<NetworkStatsManager> {
+        on { querySummaryForDevice(any(), eq(CYCLE1_START_TIME), eq(CYCLE1_END_TIME)) } doReturn
+            CYCLE1_BUCKET
+
+        on {
+            querySummaryForDevice(
+                any(),
+                eq(CYCLE2_END_TIME - DateUtils.WEEK_IN_MILLIS * 4),
+                eq(CYCLE2_END_TIME),
+            )
+        } doReturn CYCLE2_BUCKET
+
+        on { querySummaryForDevice(any(), eq(CYCLE3_START_TIME), eq(CYCLE4_END_TIME)) } doReturn
+            CYCLE3_AND_4_BUCKET
+
+        on { querySummaryForDevice(any(), eq(CYCLE3_START_TIME), eq(CYCLE3_END_TIME)) } doReturn
+            CYCLE3_BUCKET
+
+        on { querySummaryForDevice(any(), eq(CYCLE4_START_TIME), eq(CYCLE4_END_TIME)) } doReturn
+            CYCLE4_BUCKET
+    }
+
+    private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
+        on { getSystemService(NetworkStatsManager::class.java) } doReturn mockNetworkStatsManager
+    }
+
+    private val template = mock<NetworkTemplate>()
+
+    private val repository = spy(NetworkCycleDataRepository(context, template))
+
+    @Test
+    fun loadCycles_byPolicy() = runTest {
+        val policy = mock<NetworkPolicy> {
+            on { cycleIterator() } doReturn listOf(
+                Range(zonedDateTime(CYCLE1_START_TIME), zonedDateTime(CYCLE1_END_TIME))
+            ).iterator()
+        }
+        doReturn(policy).whenever(repository).getPolicy()
+
+        val cycles = repository.loadCycles()
+
+        assertThat(cycles).containsExactly(NetworkUsageData(startTime = 1, endTime = 2, usage = 11))
+    }
+
+    @Test
+    fun loadCycles_asFourWeeks() = runTest {
+        doReturn(null).whenever(repository).getPolicy()
+        doReturn(Range(CYCLE2_START_TIME, CYCLE2_END_TIME)).whenever(repository).getTimeRange()
+
+        val cycles = repository.loadCycles()
+
+        assertThat(cycles).containsExactly(
+            NetworkUsageData(
+                startTime = CYCLE2_END_TIME - DateUtils.WEEK_IN_MILLIS * 4,
+                endTime = CYCLE2_END_TIME,
+                usage = 22,
+            ),
+        )
+    }
+
+    @Test
+    fun querySummary() = runTest {
+        val summary = repository.querySummary(CYCLE3_START_TIME, CYCLE4_END_TIME)
+
+        assertThat(summary).isEqualTo(
+            NetworkCycleChartData(
+                total = NetworkUsageData(
+                    startTime = CYCLE3_START_TIME,
+                    endTime = CYCLE4_END_TIME,
+                    usage = 77,
+                ),
+                dailyUsage = listOf(
+                    NetworkUsageData(
+                        startTime = CYCLE3_START_TIME,
+                        endTime = CYCLE3_END_TIME,
+                        usage = 33,
+                    ),
+                    NetworkUsageData(
+                        startTime = CYCLE4_START_TIME,
+                        endTime = CYCLE4_END_TIME,
+                        usage = 44,
+                    ),
+                ),
+            )
+        )
+    }
+
+    private fun zonedDateTime(epochMilli: Long): ZonedDateTime? =
+        ZonedDateTime.ofInstant(Instant.ofEpochMilli(epochMilli), ZoneId.systemDefault())
+
+    private companion object {
+        const val CYCLE1_START_TIME = 1L
+        const val CYCLE1_END_TIME = 2L
+        val CYCLE1_BUCKET = mock<Bucket> {
+            on { rxBytes } doReturn 1
+            on { txBytes } doReturn 10
+        }
+
+        const val CYCLE2_START_TIME = 1695555555000L
+        const val CYCLE2_END_TIME = 1695566666000L
+        val CYCLE2_BUCKET = mock<Bucket> {
+            on { rxBytes } doReturn 2
+            on { txBytes } doReturn 20
+        }
+
+        const val CYCLE3_START_TIME = 1695555555000L
+        const val CYCLE3_END_TIME = CYCLE3_START_TIME + DateUtils.DAY_IN_MILLIS
+        val CYCLE3_BUCKET = mock<Bucket> {
+            on { rxBytes } doReturn 3
+            on { txBytes } doReturn 30
+        }
+
+        const val CYCLE4_START_TIME = CYCLE3_END_TIME
+        const val CYCLE4_END_TIME = CYCLE4_START_TIME + DateUtils.DAY_IN_MILLIS
+        val CYCLE4_BUCKET = mock<Bucket> {
+            on { rxBytes } doReturn 4
+            on { txBytes } doReturn 40
+        }
+
+        val CYCLE3_AND_4_BUCKET = mock<Bucket> {
+            on { rxBytes } doReturn 7
+            on { txBytes } doReturn 70
+        }
+    }
+}
diff --git a/tests/spa_unit/src/com/android/settings/network/apn/ApnEditPageProviderTest.kt b/tests/spa_unit/src/com/android/settings/network/apn/ApnEditPageProviderTest.kt
index 0d2dcef..d744181 100644
--- a/tests/spa_unit/src/com/android/settings/network/apn/ApnEditPageProviderTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/apn/ApnEditPageProviderTest.kt
@@ -59,6 +59,7 @@
         context.resources.getStringArray(R.array.apn_protocol_entries).toList()
     private val bearer = context.resources.getString(R.string.bearer)
     private val bearerOptions = context.resources.getStringArray(R.array.bearer_entries).toList()
+    private val passwordTitle = context.resources.getString(R.string.apn_password)
     private val apnData = mutableStateOf(
         ApnData(
             name = apnName,
@@ -241,4 +242,16 @@
         composeTestRule.onNode(hasText(bearerOptions[0]) and isFocused(), true).assertIsDisplayed()
         composeTestRule.onNode(hasText(bearerOptions[1]) and isFocused(), true).assertDoesNotExist()
     }
+
+    @Test
+    fun password_displayed() {
+        composeTestRule.setContent {
+            ApnPage(remember {
+                apnData
+            })
+        }
+        composeTestRule.onRoot().onChild().onChildAt(0)
+            .performScrollToNode(hasText(passwordTitle, true))
+        composeTestRule.onNodeWithText(passwordTitle, true).assertIsDisplayed()
+    }
 }
\ No newline at end of file
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppPreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppPreferenceTest.kt
index 9a17032..dd5b929 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppPreferenceTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/appcompat/UserAspectRatioAppPreferenceTest.kt
@@ -17,10 +17,10 @@
 package com.android.settings.spa.app.appcompat
 
 import android.content.Context
-import android.content.pm.ActivityInfo
 import android.content.pm.ApplicationInfo
+import android.content.pm.LauncherActivityInfo
+import android.content.pm.LauncherApps
 import android.content.pm.PackageManager
-import android.content.pm.ResolveInfo
 import android.provider.DeviceConfig.NAMESPACE_WINDOW_MANAGER
 import android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE
 import androidx.compose.runtime.CompositionLocalProvider
@@ -46,9 +46,9 @@
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyString
 import org.mockito.Mock
 import org.mockito.Mockito.any
-import org.mockito.Mockito.anyInt
 import org.mockito.MockitoSession
 import org.mockito.Spy
 import org.mockito.quality.Strictness
@@ -76,6 +76,12 @@
     @Mock
     private lateinit var packageManager: PackageManager
 
+    @Mock
+    private lateinit var launcherApps: LauncherApps
+
+    @Mock
+    private lateinit var launcherActivities: List<LauncherActivityInfo>
+
     @Before
     fun setUp() {
         mockSession = ExtendedMockito.mockitoSession()
@@ -86,6 +92,8 @@
             .startMocking()
         whenever(context.resources).thenReturn(resources)
         whenever(context.packageManager).thenReturn(packageManager)
+        whenever(context.getSystemService(Context.LAUNCHER_APPS_SERVICE)).thenReturn(launcherApps)
+        whenever(launcherApps.getActivityList(anyString(), any())).thenReturn(launcherActivities)
         // True is ignored but need this here or getBoolean will complain null object
         mockProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE, true)
     }
@@ -107,6 +115,8 @@
 
     @Test
     fun whenCannotDisplayAspectRatioUi_notDisplayed() {
+        whenever(launcherActivities.isEmpty()).thenReturn(true)
+
         setContent()
 
         composeTestRule.onRoot().assertIsNotDisplayed()
@@ -115,8 +125,7 @@
     @Test
     fun whenCanDisplayAspectRatioUiAndConfigFalse_notDisplayed() {
         setConfig(false)
-        whenever(packageManager.queryIntentActivities(any(), anyInt()))
-            .thenReturn(listOf(RESOLVE_INFO))
+        whenever(launcherActivities.isEmpty()).thenReturn(false)
 
         setContent()
 
@@ -127,6 +136,8 @@
     fun whenCannotDisplayAspectRatioUiAndConfigTrue_notDisplayed() {
         setConfig(true)
 
+        whenever(launcherActivities.isEmpty()).thenReturn(true)
+
         setContent()
 
         composeTestRule.onRoot().assertIsNotDisplayed()
@@ -135,9 +146,7 @@
     @Test
     fun whenCanDisplayAspectRatioUiAndConfigTrue_Displayed() {
         setConfig(true)
-        whenever(packageManager.queryIntentActivities(any(), anyInt()))
-            .thenReturn(listOf(RESOLVE_INFO))
-
+        whenever(launcherActivities.isEmpty()).thenReturn(false)
         setContent()
 
         composeTestRule.onNode(
@@ -151,8 +160,7 @@
     @Test
     fun onClick_startActivity() {
         setConfig(true)
-        whenever(packageManager.queryIntentActivities(any(), anyInt()))
-            .thenReturn(listOf(RESOLVE_INFO))
+        whenever(launcherActivities.isEmpty()).thenReturn(false)
 
         setContent()
         composeTestRule.onRoot().performClick()
@@ -196,10 +204,5 @@
             packageName = PACKAGE_NAME
             uid = UID
         }
-        private val RESOLVE_INFO = ResolveInfo().apply {
-            activityInfo = ActivityInfo().apply {
-                packageName = PACKAGE_NAME
-            }
-        }
     }
 }
\ No newline at end of file
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index 196b809..4f044c7 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -28,6 +28,7 @@
         "truth-prebuilt",
         "kotlinx_coroutines_test",
         "flag-junit",
+        "Settings-testutils2",
         // Don't add SettingsLib libraries here - you can use them directly as they are in the
         // instrumented Settings app.
     ],
diff --git a/tests/unit/src/com/android/settings/applications/appcompat/UserAspectRatioManagerTest.java b/tests/unit/src/com/android/settings/applications/appcompat/UserAspectRatioManagerTest.java
index 6cc386b..81078e8 100644
--- a/tests/unit/src/com/android/settings/applications/appcompat/UserAspectRatioManagerTest.java
+++ b/tests/unit/src/com/android/settings/applications/appcompat/UserAspectRatioManagerTest.java
@@ -32,15 +32,18 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.LauncherActivityInfo;
+import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.provider.DeviceConfig;
 
@@ -55,6 +58,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.List;
+
 /**
  * To run this test: atest SettingsUnitTests:UserAspectRatioManagerTest
  */
@@ -67,14 +72,23 @@
     private String mOriginalSettingsFlag;
     private String mOriginalFullscreenFlag;
     private String mPackageName = "com.test.mypackage";
-
+    private LauncherApps mLauncherApps;
+    private List<LauncherActivityInfo> mLauncherActivities;
     @Before
     public void setUp() {
         mContext = spy(ApplicationProvider.getApplicationContext());
         mResources = spy(mContext.getResources());
-        mUtils = new UserAspectRatioManager(mContext);
+        mLauncherApps = mock(LauncherApps.class);
+        mLauncherActivities = mock(List.class);
+        mUtils = new UserAspectRatioManager(mContext) {
+            @Override
+            LauncherApps getLauncherApps() {
+                return mLauncherApps;
+            }
+        };
 
         when(mContext.getResources()).thenReturn(mResources);
+        doReturn(mLauncherActivities).when(mLauncherApps).getActivityList(anyString(), any());
 
         mOriginalSettingsFlag = DeviceConfig.getProperty(
                 DeviceConfig.NAMESPACE_WINDOW_MANAGER, KEY_ENABLE_USER_ASPECT_RATIO_SETTINGS);
@@ -98,13 +112,14 @@
     public void testCanDisplayAspectRatioUi() {
         final ApplicationInfo canDisplay = new ApplicationInfo();
         canDisplay.packageName = "com.app.candisplay";
-        addResolveInfoLauncherEntry(canDisplay.packageName);
 
+        doReturn(false).when(mLauncherActivities).isEmpty();
         assertTrue(mUtils.canDisplayAspectRatioUi(canDisplay));
 
         final ApplicationInfo noLauncherEntry = new ApplicationInfo();
         noLauncherEntry.packageName = "com.app.nolauncherentry";
 
+        doReturn(true).when(mLauncherActivities).isEmpty();
         assertFalse(mUtils.canDisplayAspectRatioUi(noLauncherEntry));
     }
 
@@ -112,10 +127,10 @@
     public void testCanDisplayAspectRatioUi_hasLauncher_propertyFalse_returnFalse()
             throws PackageManager.NameNotFoundException {
         mockProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE, false);
+        doReturn(true).when(mLauncherActivities).isEmpty();
 
         final ApplicationInfo canDisplay = new ApplicationInfo();
         canDisplay.packageName = mPackageName;
-        addResolveInfoLauncherEntry(canDisplay.packageName);
 
         assertFalse(mUtils.canDisplayAspectRatioUi(canDisplay));
     }
@@ -124,6 +139,7 @@
     public void testCanDisplayAspectRatioUi_noLauncher_propertyTrue_returnFalse()
             throws PackageManager.NameNotFoundException {
         mockProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE, true);
+        doReturn(true).when(mLauncherActivities).isEmpty();
 
         final ApplicationInfo noLauncherEntry = new ApplicationInfo();
         noLauncherEntry.packageName = mPackageName;
@@ -267,12 +283,4 @@
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
                 KEY_ENABLE_USER_ASPECT_RATIO_FULLSCREEN, enabled, makeDefault);
     }
-
-    private void addResolveInfoLauncherEntry(String packageName) {
-        final ResolveInfo resolveInfo = mock(ResolveInfo.class);
-        final ActivityInfo activityInfo = mock(ActivityInfo.class);
-        activityInfo.packageName = packageName;
-        resolveInfo.activityInfo = activityInfo;
-        mUtils.addInfoHasLauncherEntry(resolveInfo);
-    }
 }
diff --git a/tests/unit/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest.java b/tests/unit/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest.java
index ae35431..4aa38ae 100644
--- a/tests/unit/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest.java
+++ b/tests/unit/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest.java
@@ -18,12 +18,14 @@
 
 import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngleAsSystemDriverController.ANGLE_DRIVER_SUFFIX;
 import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngleAsSystemDriverController.Injector;
+import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngleAsSystemDriverController.PROPERTY_DEBUG_ANGLE_DEVELOPER_OPTION;
 import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngleAsSystemDriverController.PROPERTY_PERSISTENT_GRAPHICS_EGL;
 import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngleAsSystemDriverController.PROPERTY_RO_GFX_ANGLE_SUPPORTED;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.when;
 
@@ -98,6 +100,8 @@
         }
 
         mContext = ApplicationProvider.getApplicationContext();
+        when(mSystemPropertiesMock.getBoolean(eq(PROPERTY_DEBUG_ANGLE_DEVELOPER_OPTION),
+                                              anyBoolean())).thenReturn(true);
 
         // Construct a GraphicsDriverEnableAngleAsSystemDriverController with two Overrides:
         // 1) Override the mSystemProperties with mSystemPropertiesMock,
diff --git a/tests/unit/src/com/android/settings/fingerprint2/domain/interactor/FingerprintManagerInteractorTest.kt b/tests/unit/src/com/android/settings/fingerprint2/domain/interactor/FingerprintManagerInteractorTest.kt
index de2c494..f0d0a0a 100644
--- a/tests/unit/src/com/android/settings/fingerprint2/domain/interactor/FingerprintManagerInteractorTest.kt
+++ b/tests/unit/src/com/android/settings/fingerprint2/domain/interactor/FingerprintManagerInteractorTest.kt
@@ -26,12 +26,12 @@
 import android.os.Handler
 import androidx.test.core.app.ApplicationProvider
 import com.android.settings.biometrics.GatekeeperPasswordProvider
-import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractor
+import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
 import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
+import com.android.settings.biometrics.fingerprint2.shared.model.EnrollReason
 import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptViewModel
 import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintViewModel
-import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.EnrollReason.FindSensor
-import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerEnrollStateViewModel
+import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollStateViewModel
 import com.android.settings.password.ChooseLockSettingsHelper
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.cancelAndJoin
@@ -283,7 +283,7 @@
     testScope.runTest {
       val token = byteArrayOf(5, 3, 2)
       var result: FingerEnrollStateViewModel? = null
-      val job = launch { underTest.enroll(token, FindSensor).collect { result = it } }
+      val job = launch { underTest.enroll(token, EnrollReason.FindSensor).collect { result = it } }
       val enrollCallback: ArgumentCaptor<FingerprintManager.EnrollmentCallback> = argumentCaptor()
       runCurrent()
 
@@ -307,7 +307,7 @@
     testScope.runTest {
       val token = byteArrayOf(5, 3, 2)
       var result: FingerEnrollStateViewModel? = null
-      val job = launch { underTest.enroll(token, FindSensor).collect { result = it } }
+      val job = launch { underTest.enroll(token, EnrollReason.FindSensor).collect { result = it } }
       val enrollCallback: ArgumentCaptor<FingerprintManager.EnrollmentCallback> = argumentCaptor()
       runCurrent()
 
@@ -331,7 +331,7 @@
     testScope.runTest {
       val token = byteArrayOf(5, 3, 2)
       var result: FingerEnrollStateViewModel? = null
-      val job = launch { underTest.enroll(token, FindSensor).collect { result = it } }
+      val job = launch { underTest.enroll(token, EnrollReason.FindSensor).collect { result = it } }
       val enrollCallback: ArgumentCaptor<FingerprintManager.EnrollmentCallback> = argumentCaptor()
       runCurrent()
 
diff --git a/tests/unit/src/com/android/settings/fingerprint2/settings/viewmodel/FingerprintSettingsNavigationViewModelTest.kt b/tests/unit/src/com/android/settings/fingerprint2/ui/settings/FingerprintSettingsNavigationViewModelTest.kt
similarity index 94%
rename from tests/unit/src/com/android/settings/fingerprint2/settings/viewmodel/FingerprintSettingsNavigationViewModelTest.kt
rename to tests/unit/src/com/android/settings/fingerprint2/ui/settings/FingerprintSettingsNavigationViewModelTest.kt
index 6bb8a16..d4dbec5 100644
--- a/tests/unit/src/com/android/settings/fingerprint2/settings/viewmodel/FingerprintSettingsNavigationViewModelTest.kt
+++ b/tests/unit/src/com/android/settings/fingerprint2/ui/settings/FingerprintSettingsNavigationViewModelTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settings.fingerprint2.settings.viewmodel
+package com.android.settings.fingerprint2.ui.settings
 
 import androidx.arch.core.executor.testing.InstantTaskExecutorRule
 import com.android.settings.biometrics.BiometricEnrollBase
@@ -26,7 +26,7 @@
 import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.LaunchConfirmDeviceCredential
 import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.NextStepViewModel
 import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.ShowSettings
-import com.android.settings.fingerprint2.domain.interactor.FakeFingerprintManagerInteractor
+import com.android.settings.testutils2.FakeFingerprintManagerInteractor
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
@@ -133,22 +133,6 @@
     }
 
   @Test
-  fun firstEnrollment_fails() =
-    testScope.runTest {
-      fakeFingerprintManagerInteractor.enrolledFingerprintsInternal = mutableListOf()
-
-      var nextStep: NextStepViewModel? = null
-      val job = launch { underTest.nextStep.collect { nextStep = it } }
-
-      underTest.onConfirmDevice(true, 10L)
-      underTest.onEnrollFirstFailure("We failed!!")
-      runCurrent()
-
-      assertThat(nextStep).isInstanceOf(FinishSettings::class.java)
-      job.cancel()
-    }
-
-  @Test
   fun firstEnrollment_failsWithReason() =
     testScope.runTest {
       fakeFingerprintManagerInteractor.enrolledFingerprintsInternal = mutableListOf()
diff --git a/tests/unit/src/com/android/settings/fingerprint2/settings/viewmodel/FingerprintSettingsViewModelTest.kt b/tests/unit/src/com/android/settings/fingerprint2/ui/settings/FingerprintSettingsViewModelTest.kt
similarity index 86%
rename from tests/unit/src/com/android/settings/fingerprint2/settings/viewmodel/FingerprintSettingsViewModelTest.kt
rename to tests/unit/src/com/android/settings/fingerprint2/ui/settings/FingerprintSettingsViewModelTest.kt
index e8a4d55..fb1d05a 100644
--- a/tests/unit/src/com/android/settings/fingerprint2/settings/viewmodel/FingerprintSettingsViewModelTest.kt
+++ b/tests/unit/src/com/android/settings/fingerprint2/ui/settings/FingerprintSettingsViewModelTest.kt
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package com.android.settings.fingerprint2.settings.viewmodel
+package com.android.settings.fingerprint2.ui.settings
 
-import android.hardware.biometrics.SensorProperties
-import android.hardware.fingerprint.FingerprintSensorProperties
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
 import androidx.arch.core.executor.testing.InstantTaskExecutorRule
 import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptViewModel
+import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintSensorPropertyViewModel
 import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintViewModel
+import com.android.settings.biometrics.fingerprint2.shared.model.SensorStrength
+import com.android.settings.biometrics.fingerprint2.shared.model.SensorType
 import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.FingerprintSettingsNavigationViewModel
 import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.FingerprintSettingsViewModel
 import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.PreferenceViewModel
-import com.android.settings.fingerprint2.domain.interactor.FakeFingerprintManagerInteractor
+import com.android.settings.testutils2.FakeFingerprintManagerInteractor
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.collectLatest
@@ -95,16 +95,12 @@
   @Test
   fun authenticate_DoesNotRun_ifOptical() =
     testScope.runTest {
-      fakeFingerprintManagerInteractor.sensorProps =
-        listOf(
-          FingerprintSensorPropertiesInternal(
-            0 /* sensorId */,
-            SensorProperties.STRENGTH_STRONG,
-            5 /* maxEnrollmentsPerUser */,
-            emptyList() /* ComponentInfoInternal */,
-            FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
-            true /* resetLockoutRequiresHardwareAuthToken */
-          )
+      fakeFingerprintManagerInteractor.sensorProp =
+        FingerprintSensorPropertyViewModel(
+          0 /* sensorId */,
+          SensorStrength.Strong,
+          5 /* maxEnrollmentsPerUser */,
+          SensorType.Optical,
         )
       fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
         mutableListOf(FingerprintViewModel("a", 1, 3L))
@@ -135,16 +131,12 @@
   @Test
   fun authenticate_DoesNotRun_ifUltrasonic() =
     testScope.runTest {
-      fakeFingerprintManagerInteractor.sensorProps =
-        listOf(
-          FingerprintSensorPropertiesInternal(
-            0 /* sensorId */,
-            SensorProperties.STRENGTH_STRONG,
-            5 /* maxEnrollmentsPerUser */,
-            emptyList() /* ComponentInfoInternal */,
-            FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC,
-            true /* resetLockoutRequiresHardwareAuthToken */
-          )
+      fakeFingerprintManagerInteractor.sensorProp =
+        FingerprintSensorPropertyViewModel(
+          0 /* sensorId */,
+          SensorStrength.Strong,
+          5 /* maxEnrollmentsPerUser */,
+          SensorType.Ultrasonic,
         )
       fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
         mutableListOf(FingerprintViewModel("a", 1, 3L))
@@ -173,16 +165,12 @@
   @Test
   fun authenticate_DoesRun_ifNotUdfps() =
     testScope.runTest {
-      fakeFingerprintManagerInteractor.sensorProps =
-        listOf(
-          FingerprintSensorPropertiesInternal(
-            0 /* sensorId */,
-            SensorProperties.STRENGTH_STRONG,
-            5 /* maxEnrollmentsPerUser */,
-            emptyList() /* ComponentInfoInternal */,
-            FingerprintSensorProperties.TYPE_POWER_BUTTON,
-            true /* resetLockoutRequiresHardwareAuthToken */
-          )
+      fakeFingerprintManagerInteractor.sensorProp =
+        FingerprintSensorPropertyViewModel(
+          0 /* sensorId */,
+          SensorStrength.Strong,
+          5 /* maxEnrollmentsPerUser */,
+          SensorType.SFPS
         )
       fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
         mutableListOf(FingerprintViewModel("a", 1, 3L))
@@ -383,16 +371,12 @@
     }
 
   private fun setupAuth(): MutableList<FingerprintViewModel> {
-    fakeFingerprintManagerInteractor.sensorProps =
-      listOf(
-        FingerprintSensorPropertiesInternal(
-          0 /* sensorId */,
-          SensorProperties.STRENGTH_STRONG,
-          5 /* maxEnrollmentsPerUser */,
-          emptyList() /* ComponentInfoInternal */,
-          FingerprintSensorProperties.TYPE_POWER_BUTTON,
-          true /* resetLockoutRequiresHardwareAuthToken */
-        )
+    fakeFingerprintManagerInteractor.sensorProp =
+      FingerprintSensorPropertyViewModel(
+        0 /* sensorId */,
+        SensorStrength.Strong,
+        5 /* maxEnrollmentsPerUser */,
+        SensorType.SFPS
       )
     val fingerprints =
       mutableListOf(FingerprintViewModel("a", 1, 3L), FingerprintViewModel("b", 2, 5L))
diff --git a/tests/unit/src/com/android/settings/localepicker/TermsOfAddressFeminineControllerTest.java b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressFeminineControllerTest.java
new file mode 100644
index 0000000..c04e5f9
--- /dev/null
+++ b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressFeminineControllerTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.localepicker;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.os.Looper;
+
+import com.android.settings.widget.TickButtonPreference;
+
+import androidx.preference.PreferenceManager;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class TermsOfAddressFeminineControllerTest {
+
+    private static final String KEY_CATEGORY_TERMS_OF_ADDRESS = "key_category_terms_of_address";
+    private static final String KEY_FEMININE = "key_terms_of_address_feminine";
+    private static final String KEY_MASCULINE = "key_terms_of_address_masculine";
+    private static final String KEY_NEUTRAL = "key_terms_of_address_neutral";
+    private static final String KEY_NOT_SPECIFIED = "key_terms_of_address_not_specified";
+
+    private Context mContext;
+    private PreferenceManager mPreferenceManager;
+    private PreferenceCategory mPreferenceCategory;
+    private PreferenceScreen mPreferenceScreen;
+    private TermsOfAddressFeminineController mController;
+    private TickButtonPreference mFemininePreference;
+    private TickButtonPreference mMasculinePreference;
+    private TickButtonPreference mNotSpecifiedPreference;
+    private TickButtonPreference mNeutralPreference;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(ApplicationProvider.getApplicationContext());
+
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+
+        mPreferenceManager = new PreferenceManager(mContext);
+        mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
+        mPreferenceCategory = new PreferenceCategory(mContext);
+        mPreferenceCategory.setKey(KEY_CATEGORY_TERMS_OF_ADDRESS);
+        mNotSpecifiedPreference = new TickButtonPreference(mContext);
+        mNotSpecifiedPreference.setKey(KEY_NOT_SPECIFIED);
+        mFemininePreference = new TickButtonPreference(mContext);
+        mFemininePreference.setKey(KEY_FEMININE);
+        mMasculinePreference = new TickButtonPreference(mContext);
+        mMasculinePreference.setKey(KEY_MASCULINE);
+        mNeutralPreference = new TickButtonPreference(mContext);
+        mNeutralPreference.setKey(KEY_NEUTRAL);
+        mPreferenceScreen.addPreference(mPreferenceCategory);
+        mPreferenceScreen.addPreference(mNotSpecifiedPreference);
+        mPreferenceScreen.addPreference(mFemininePreference);
+        mPreferenceScreen.addPreference(mMasculinePreference);
+        mPreferenceScreen.addPreference(mNeutralPreference);
+        mController = new TermsOfAddressFeminineController(mContext, KEY_FEMININE);
+        mController.displayPreference(mPreferenceScreen);
+    }
+
+    @Test
+    public void displayPreference_setGrammaticalGenderIsFeminine_FeminineIsSelected() {
+        TickButtonPreference selectedPreference =
+                (TickButtonPreference) mPreferenceScreen.getPreference(2);
+        TickButtonPreference pref = (TickButtonPreference) mPreferenceScreen.getPreference(1);
+
+        selectedPreference.performClick();
+
+        assertThat(selectedPreference.getKey()).isEqualTo(KEY_FEMININE);
+        assertThat(selectedPreference.isSelected()).isTrue();
+        assertThat(pref.isSelected()).isFalse();
+    }
+}
diff --git a/tests/unit/src/com/android/settings/localepicker/TermsOfAddressMasculineControllerTest.java b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressMasculineControllerTest.java
new file mode 100644
index 0000000..c2298be
--- /dev/null
+++ b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressMasculineControllerTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.localepicker;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.os.Looper;
+
+import com.android.settings.widget.TickButtonPreference;
+
+import androidx.preference.PreferenceManager;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class TermsOfAddressMasculineControllerTest {
+
+    private static final String KEY_CATEGORY_TERMS_OF_ADDRESS = "key_category_terms_of_address";
+    private static final String KEY_FEMININE = "key_terms_of_address_feminine";
+    private static final String KEY_MASCULINE = "key_terms_of_address_masculine";
+    private static final String KEY_NEUTRAL = "key_terms_of_address_neutral";
+    private static final String KEY_NOT_SPECIFIED = "key_terms_of_address_not_specified";
+
+    private Context mContext;
+    private PreferenceManager mPreferenceManager;
+    private PreferenceCategory mPreferenceCategory;
+    private PreferenceScreen mPreferenceScreen;
+    private TermsOfAddressMasculineController mController;
+    private TickButtonPreference mFemininePreference;
+    private TickButtonPreference mMasculinePreference;
+    private TickButtonPreference mNotSpecifiedPreference;
+    private TickButtonPreference mNeutralPreference;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(ApplicationProvider.getApplicationContext());
+
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+
+        mPreferenceManager = new PreferenceManager(mContext);
+        mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
+        mPreferenceCategory = new PreferenceCategory(mContext);
+        mPreferenceCategory.setKey(KEY_CATEGORY_TERMS_OF_ADDRESS);
+        mNotSpecifiedPreference = new TickButtonPreference(mContext);
+        mNotSpecifiedPreference.setKey(KEY_NOT_SPECIFIED);
+        mFemininePreference = new TickButtonPreference(mContext);
+        mFemininePreference.setKey(KEY_FEMININE);
+        mMasculinePreference = new TickButtonPreference(mContext);
+        mMasculinePreference.setKey(KEY_MASCULINE);
+        mNeutralPreference = new TickButtonPreference(mContext);
+        mNeutralPreference.setKey(KEY_NEUTRAL);
+        mPreferenceScreen.addPreference(mPreferenceCategory);
+        mPreferenceScreen.addPreference(mNotSpecifiedPreference);
+        mPreferenceScreen.addPreference(mFemininePreference);
+        mPreferenceScreen.addPreference(mMasculinePreference);
+        mPreferenceScreen.addPreference(mNeutralPreference);
+        mController = new TermsOfAddressMasculineController(mContext, KEY_MASCULINE);
+        mController.displayPreference(mPreferenceScreen);
+    }
+
+    @Test
+    public void displayPreference_setGrammaticalGenderIsMasculine_MasculineIsSelected() {
+        TickButtonPreference selectedPreference =
+                (TickButtonPreference) mPreferenceScreen.getPreference(3);
+        TickButtonPreference pref = (TickButtonPreference) mPreferenceScreen.getPreference(1);
+
+        selectedPreference.performClick();
+
+        assertThat(selectedPreference.getKey()).isEqualTo(KEY_MASCULINE);
+        assertThat(selectedPreference.isSelected()).isTrue();
+        assertThat(pref.isSelected()).isFalse();
+    }
+}
diff --git a/tests/unit/src/com/android/settings/localepicker/TermsOfAddressNeutralControllerTest.java b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressNeutralControllerTest.java
new file mode 100644
index 0000000..fb207fc
--- /dev/null
+++ b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressNeutralControllerTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.localepicker;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.os.Looper;
+
+import com.android.settings.widget.TickButtonPreference;
+
+import androidx.preference.PreferenceManager;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class TermsOfAddressNeutralControllerTest {
+
+    private static final String KEY_CATEGORY_TERMS_OF_ADDRESS = "key_category_terms_of_address";
+    private static final String KEY_FEMININE = "key_terms_of_address_feminine";
+    private static final String KEY_MASCULINE = "key_terms_of_address_masculine";
+    private static final String KEY_NEUTRAL = "key_terms_of_address_neutral";
+    private static final String KEY_NOT_SPECIFIED = "key_terms_of_address_not_specified";
+
+    private Context mContext;
+    private PreferenceManager mPreferenceManager;
+    private PreferenceCategory mPreferenceCategory;
+    private PreferenceScreen mPreferenceScreen;
+    private TermsOfAddressNeutralController mController;
+    private TickButtonPreference mFemininePreference;
+    private TickButtonPreference mMasculinePreference;
+    private TickButtonPreference mNotSpecifiedPreference;
+    private TickButtonPreference mNeutralPreference;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(ApplicationProvider.getApplicationContext());
+
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+
+        mPreferenceManager = new PreferenceManager(mContext);
+        mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
+        mPreferenceCategory = new PreferenceCategory(mContext);
+        mPreferenceCategory.setKey(KEY_CATEGORY_TERMS_OF_ADDRESS);
+        mNotSpecifiedPreference = new TickButtonPreference(mContext);
+        mNotSpecifiedPreference.setKey(KEY_NOT_SPECIFIED);
+        mFemininePreference = new TickButtonPreference(mContext);
+        mFemininePreference.setKey(KEY_FEMININE);
+        mMasculinePreference = new TickButtonPreference(mContext);
+        mMasculinePreference.setKey(KEY_MASCULINE);
+        mNeutralPreference = new TickButtonPreference(mContext);
+        mNeutralPreference.setKey(KEY_NEUTRAL);
+        mPreferenceScreen.addPreference(mPreferenceCategory);
+        mPreferenceScreen.addPreference(mNotSpecifiedPreference);
+        mPreferenceScreen.addPreference(mFemininePreference);
+        mPreferenceScreen.addPreference(mMasculinePreference);
+        mPreferenceScreen.addPreference(mNeutralPreference);
+        mController = new TermsOfAddressNeutralController(mContext, KEY_NEUTRAL);
+        mController.displayPreference(mPreferenceScreen);
+    }
+
+    @Test
+    public void displayPreference_setGrammaticalGenderIsNotSpecified_NotSpecifiedIsSelected() {
+        TickButtonPreference selectedPreference =
+                (TickButtonPreference) mPreferenceScreen.getPreference(4);
+        TickButtonPreference pref = (TickButtonPreference) mPreferenceScreen.getPreference(1);
+
+        selectedPreference.performClick();
+
+        assertThat(selectedPreference.getKey()).isEqualTo(KEY_NEUTRAL);
+        assertThat(selectedPreference.isSelected()).isTrue();
+        assertThat(pref.isSelected()).isFalse();
+    }
+}
diff --git a/tests/unit/src/com/android/settings/localepicker/TermsOfAddressNotSpecifiedControllerTest.java b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressNotSpecifiedControllerTest.java
new file mode 100644
index 0000000..8492c3b
--- /dev/null
+++ b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressNotSpecifiedControllerTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.localepicker;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.os.Looper;
+
+import com.android.settings.widget.TickButtonPreference;
+
+import androidx.preference.PreferenceManager;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class TermsOfAddressNotSpecifiedControllerTest {
+
+    private static final String KEY_CATEGORY_TERMS_OF_ADDRESS = "key_category_terms_of_address";
+    private static final String KEY_FEMININE = "key_terms_of_address_feminine";
+    private static final String KEY_MASCULINE = "key_terms_of_address_masculine";
+    private static final String KEY_NEUTRAL = "key_terms_of_address_neutral";
+    private static final String KEY_NOT_SPECIFIED = "key_terms_of_address_not_specified";
+
+    private Context mContext;
+    private PreferenceManager mPreferenceManager;
+    private PreferenceCategory mPreferenceCategory;
+    private PreferenceScreen mPreferenceScreen;
+    private TermsOfAddressNotSpecifiedController mController;
+    private TickButtonPreference mFemininePreference;
+    private TickButtonPreference mMasculinePreference;
+    private TickButtonPreference mNotSpecifiedPreference;
+    private TickButtonPreference mNeutralPreference;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(ApplicationProvider.getApplicationContext());
+
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+
+        mPreferenceManager = new PreferenceManager(mContext);
+        mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
+        mPreferenceCategory = new PreferenceCategory(mContext);
+        mPreferenceCategory.setKey(KEY_CATEGORY_TERMS_OF_ADDRESS);
+        mNotSpecifiedPreference = new TickButtonPreference(mContext);
+        mNotSpecifiedPreference.setKey(KEY_NOT_SPECIFIED);
+        mFemininePreference = new TickButtonPreference(mContext);
+        mFemininePreference.setKey(KEY_FEMININE);
+        mMasculinePreference = new TickButtonPreference(mContext);
+        mMasculinePreference.setKey(KEY_MASCULINE);
+        mNeutralPreference = new TickButtonPreference(mContext);
+        mNeutralPreference.setKey(KEY_NEUTRAL);
+        mPreferenceScreen.addPreference(mPreferenceCategory);
+        mPreferenceScreen.addPreference(mNotSpecifiedPreference);
+        mPreferenceScreen.addPreference(mFemininePreference);
+        mPreferenceScreen.addPreference(mMasculinePreference);
+        mPreferenceScreen.addPreference(mNeutralPreference);
+        mController = new TermsOfAddressNotSpecifiedController(mContext, KEY_NOT_SPECIFIED);
+        mController.displayPreference(mPreferenceScreen);
+    }
+
+    @Test
+    public void displayPreference_setGrammaticalGenderIsNotSpecified_NotSpecifiedIsSelected() {
+        TickButtonPreference selectedPreference =
+                (TickButtonPreference) mPreferenceScreen.getPreference(1);
+        TickButtonPreference pref = (TickButtonPreference) mPreferenceScreen.getPreference(2);
+
+        selectedPreference.performClick();
+
+        assertThat(selectedPreference.getKey()).isEqualTo(KEY_NOT_SPECIFIED);
+        assertThat(selectedPreference.isSelected()).isTrue();
+        assertThat(pref.isSelected()).isFalse();
+    }
+}