Merge "Remove LooperMode.LEGACY usage from settings/development" into main
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 194d017..4b38062 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -147,12 +147,13 @@
     <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
     <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
     <uses-permission android:name="android.permission.GET_BACKGROUND_INSTALLED_PACKAGES" />
+    <uses-permission android:name="android.permission.SATELLITE_COMMUNICATION" />
 
     <application
             android:name=".SettingsApplication"
             android:label="@string/settings_label"
             android:icon="@drawable/ic_launcher_settings"
-            android:theme="@style/Theme.Settings.NoActionBar"
+            android:theme="@style/Theme.Settings"
             android:hardwareAccelerated="true"
             android:requiredForAllUsers="true"
             android:supportsRtl="true"
diff --git a/res/drawable/accessibility_shortcut_type_quick_settings.xml b/res/drawable/accessibility_shortcut_type_quick_settings.xml
index a801347..112250b 100644
--- a/res/drawable/accessibility_shortcut_type_quick_settings.xml
+++ b/res/drawable/accessibility_shortcut_type_quick_settings.xml
@@ -28,7 +28,7 @@
             android:pathData="M24,0L288,0A24,24 0,0 1,312 24L312,106A24,24 0,0 1,288 130L24,130A24,24 0,0 1,0 106L0,24A24,24 0,0 1,24 0z"/>
         <path
             android:pathData="M24,0L288,0A24,24 0,0 1,312 24L312,106A24,24 0,0 1,288 130L24,130A24,24 0,0 1,0 106L0,24A24,24 0,0 1,24 0z"
-            android:fillColor="#ffffff"/>
+            android:fillColor="@color/settingslib_protection_color"/>
         <path
             android:pathData="M209,139.62H210V138.62V32C210,24.82 204.18,19 197,19H115C107.82,19 102,24.82 102,32V138.62V139.62H103H209Z"
             android:strokeWidth="2"
diff --git a/res/layout/fingerprint_v2_udfps_enroll_enrolling.xml b/res/layout/fingerprint_v2_udfps_enroll_enrolling.xml
index 32df665..ddd2c30 100644
--- a/res/layout/fingerprint_v2_udfps_enroll_enrolling.xml
+++ b/res/layout/fingerprint_v2_udfps_enroll_enrolling.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  ~ Copyright (C) 2023 The Android Open Source Project
+  ~ Copyright (C) 2024 The Android Open Source Project
   ~
   ~ Licensed under the Apache License, Version 2.0 (the "License");
   ~ you may not use this file except in compliance with the License.
@@ -15,56 +15,77 @@
   ~ limitations under the License.
   -->
 
-<com.google.android.setupdesign.GlifLayout
+<LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-
     android:id="@+id/setup_wizard_layout"
     style="?attr/fingerprint_layout_theme"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    >
+    android:orientation="vertical">
 
-    <LinearLayout
-        style="@style/SudContentFrame"
+    <!-- This is used to grab style attributes and apply them
+    to this layout -->
+    <com.google.android.setupdesign.GlifLayout
+        android:id="@+id/dummy_glif_layout"
+        style="?attr/fingerprint_layout_theme"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:visibility="gone"
+        />
+
+    <ImageView
+        android:id="@+id/sud_layout_icon"
+        style="@style/SudGlifIcon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:scaleType="fitStart"
+        android:src="@drawable/ic_lock" />
+
+    <TextView
+        android:id="@+id/title"
+        style="@style/SudGlifHeaderTitle"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
+        android:layout_height="80dp"
+        android:ellipsize="end"
+        android:lines="2"
+        />
+
+    <TextView
+        android:id="@+id/description"
+        style="@style/SudDescription.Glif"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:ellipsize="end"
+        android:lines="3"
+        android:paddingLeft="10dp"
+        android:paddingRight="10dp"
+        />
+
+
+    <com.airbnb.lottie.LottieAnimationView
+        android:id="@+id/illustration_lottie"
+        android:layout_width="match_parent"
+        android:layout_height="200dp"
         android:clipChildren="false"
         android:clipToPadding="false"
-        android:orientation="vertical">
+        android:paddingLeft="10dp"
+        android:paddingRight="10dp"
+        android:scaleType="centerInside"
+        app:lottie_autoPlay="true"
+        app:lottie_loop="true"
+        app:lottie_speed=".85" />
 
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_weight="1"
-            android:gravity="center|bottom"
-            android:orientation="vertical">
+    <FrameLayout
+        android:id="@+id/layout_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_gravity="center_horizontal|bottom"
+        android:clipToPadding="false"
+        >
 
-            <FrameLayout
-                android:id="@+id/layout_container"
-                android:layout_width="200dp"
-                android:layout_height="200dp"
-                android:layout_gravity="center_horizontal|bottom"
-                android:clipChildren="false"
-                android:clipToPadding="false"
-                tools:ignore="Suspicious0dp">
-
-                <!-- Animation res MUST be set in code -->
-                <com.airbnb.lottie.LottieAnimationView
-                    android:id="@+id/illustration_lottie"
-                    android:layout_width="200dp"
-                    android:layout_height="200dp"
-                    android:clipChildren="false"
-                    android:clipToPadding="false"
-                    android:scaleType="centerInside"
-                    app:lottie_autoPlay="true"
-                    app:lottie_loop="true"
-                    app:lottie_speed=".85" />
-
-            </FrameLayout>
-        </LinearLayout>
-    </LinearLayout>
+        <include layout="@layout/fingerprint_v2_udfps_enroll_view" />
+    </FrameLayout>
 
 
-</com.google.android.setupdesign.GlifLayout>
+</LinearLayout>
diff --git a/res/layout/fingerprint_v2_udfps_enroll_view.xml b/res/layout/fingerprint_v2_udfps_enroll_view.xml
new file mode 100644
index 0000000..20df6e1
--- /dev/null
+++ b/res/layout/fingerprint_v2_udfps_enroll_view.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+
+<com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.widget.UdfpsEnrollViewV2
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/udfps_animation_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <ImageView
+        android:id="@+id/udfps_enroll_animation_fp_progress_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        />
+
+    <ImageView
+        android:id="@+id/udfps_enroll_animation_fp_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        />
+
+</com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.widget.UdfpsEnrollViewV2>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0673a10..408ba8c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -10245,10 +10245,10 @@
     <!-- Switch label to enable the Data Saver feature [CHAR LIMIT=NONE] -->
     <string name="data_saver_switch_title">Use Data Saver</string>
 
-    <!-- Title for switch to allow app unrestricted data usage [CHAR LIMIT=30] -->
+    <!-- Title for switch to allow app unrestricted data usage [CHAR LIMIT=NONE] -->
     <string name="unrestricted_app_title">Unrestricted data usage</string>
 
-    <!-- Title for switch to allow app unrestricted data usage [CHAR LIMIT=75] -->
+    <!-- Title for switch to allow app unrestricted data usage [CHAR LIMIT=NONE] -->
     <string name="unrestricted_app_summary">Allow unrestricted data access when Data Saver is on</string>
 
     <!-- Button to switch the default home app [CHAR LIMIT=60] -->
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index f09175f..d44d727 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -1387,20 +1387,19 @@
      * @param activity the Activity need to setup the edge to edge feature.
      */
     public static void setupEdgeToEdge(@NonNull FragmentActivity activity) {
-        if (com.android.window.flags.Flags.enforceEdgeToEdge()) {
-            ViewCompat.setOnApplyWindowInsetsListener(activity.findViewById(android.R.id.content),
-                    (v, windowInsets) -> {
-                        Insets insets = windowInsets.getInsets(
-                                WindowInsetsCompat.Type.systemBars()
-                                        | WindowInsetsCompat.Type.ime());
-                        // Apply the insets paddings to the view.
-                        v.setPadding(insets.left, insets.top, insets.right, insets.bottom);
+        ViewCompat.setOnApplyWindowInsetsListener(activity.findViewById(android.R.id.content),
+                (v, windowInsets) -> {
+                    Insets insets = windowInsets.getInsets(
+                            WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.ime());
+                    int statusBarHeight = activity.getWindow().getDecorView().getRootWindowInsets()
+                            .getInsets(WindowInsetsCompat.Type.statusBars()).top;
+                    // Apply the insets paddings to the view.
+                    v.setPadding(insets.left, statusBarHeight, insets.right, insets.bottom);
 
-                        // Return CONSUMED if you don't want the window insets to keep being
-                        // passed down to descendant views.
-                        return WindowInsetsCompat.CONSUMED;
-                    });
-        }
+                    // Return CONSUMED if you don't want the window insets to keep being
+                    // passed down to descendant views.
+                    return WindowInsetsCompat.CONSUMED;
+                });
     }
 
     private static FaceManager.RemovalCallback faceManagerRemovalCallback(int userId) {
diff --git a/src/com/android/settings/accessibility/AccessibilityShortcutsTutorial.java b/src/com/android/settings/accessibility/AccessibilityShortcutsTutorial.java
index fd11ab0..306bba7 100644
--- a/src/com/android/settings/accessibility/AccessibilityShortcutsTutorial.java
+++ b/src/com/android/settings/accessibility/AccessibilityShortcutsTutorial.java
@@ -460,6 +460,8 @@
         final View image =
                 createIllustrationView(context,
                         R.drawable.a11y_shortcut_type_quick_settings);
+        // Remove the unneeded background, since the main image already includes a background
+        image.findViewById(R.id.image_background).setVisibility(GONE);
         final int numFingers = AccessibilityUtil.isTouchExploreEnabled(context) ? 2 : 1;
         Map<String, Object> arguments = new ArrayMap<>();
         arguments.put("count", numFingers);
diff --git a/src/com/android/settings/accessibility/ContrastPreferenceController.java b/src/com/android/settings/accessibility/ContrastPreferenceController.java
index 4e9a9ec..33d3087 100644
--- a/src/com/android/settings/accessibility/ContrastPreferenceController.java
+++ b/src/com/android/settings/accessibility/ContrastPreferenceController.java
@@ -33,6 +33,7 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return Flags.enableColorContrastControl() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+        // Hide color contrast entry point inside Accessibility settings.
+        return CONDITIONALLY_UNAVAILABLE;
     }
 }
diff --git a/src/com/android/settings/accessibility/PreviewSizeSeekBarController.java b/src/com/android/settings/accessibility/PreviewSizeSeekBarController.java
index f268a40..7f10af7 100644
--- a/src/com/android/settings/accessibility/PreviewSizeSeekBarController.java
+++ b/src/com/android/settings/accessibility/PreviewSizeSeekBarController.java
@@ -210,8 +210,7 @@
             return;
         }
 
-        if (Flags.removeQsTooltipInSuw()
-                && mContext instanceof Activity
+        if (mContext instanceof Activity
                 && WizardManagerHelper.isAnySetupWizard(((Activity) mContext).getIntent())) {
             // Don't show QuickSettingsTooltip in Setup Wizard
             return;
diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
index 137be21..e62e473 100644
--- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
@@ -931,9 +931,7 @@
         }
 
         Activity activity = getActivity();
-        if (com.android.settings.accessibility.Flags.removeQsTooltipInSuw()
-                && activity != null
-                && WizardManagerHelper.isAnySetupWizard(activity.getIntent())) {
+        if (activity != null && WizardManagerHelper.isAnySetupWizard(activity.getIntent())) {
             // Don't show QuickSettingsTooltip in Setup Wizard
             return;
         }
diff --git a/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragment.java b/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragment.java
index 036190b..a4eaf37 100644
--- a/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragment.java
@@ -54,6 +54,7 @@
 import androidx.preference.Preference;
 import androidx.recyclerview.widget.RecyclerView;
 
+import com.android.internal.accessibility.common.ShortcutConstants;
 import com.android.internal.accessibility.dialog.AccessibilityTarget;
 import com.android.internal.accessibility.dialog.AccessibilityTargetHelper;
 import com.android.settings.R;
@@ -204,7 +205,7 @@
         // TODO(b/325664350): Implement shortcut type for "all shortcuts"
         List<AccessibilityTarget> accessibilityTargets =
                 AccessibilityTargetHelper.getInstalledTargets(
-                        activity.getBaseContext(), AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY);
+                        activity.getBaseContext(), ShortcutConstants.UserShortcutType.HARDWARE);
 
         Pair<String, String> titles = getTitlesFromAccessibilityTargetList(
                 mShortcutTargets,
diff --git a/src/com/android/settings/biometrics/activeunlock/ActiveUnlockStatusUtils.java b/src/com/android/settings/biometrics/activeunlock/ActiveUnlockStatusUtils.java
index 2eee9df..4ff2e90 100644
--- a/src/com/android/settings/biometrics/activeunlock/ActiveUnlockStatusUtils.java
+++ b/src/com/android/settings/biometrics/activeunlock/ActiveUnlockStatusUtils.java
@@ -22,7 +22,6 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ComponentInfo;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
 import android.provider.DeviceConfig;
@@ -38,8 +37,6 @@
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.core.BasePreferenceController.AvailabilityStatus;
 
-import java.util.List;
-
 /** Utilities for active unlock details shared between Security Settings and Safety Center. */
 public class ActiveUnlockStatusUtils {
 
@@ -98,18 +95,14 @@
             Log.i(TAG, "authority not set");
             return null;
         }
-        final List<PackageInfo> packageInfos =
-                mContext.getPackageManager().getInstalledPackages(
-                        PackageManager.PackageInfoFlags.of(PackageManager.GET_PROVIDERS));
-        for (PackageInfo packageInfo : packageInfos) {
-            final ProviderInfo[] providers = packageInfo.providers;
-            if (providers != null) {
-                for (ProviderInfo provider : providers) {
-                    if (authority.equals(provider.authority) && isSystemApp(provider)) {
-                        return authority;
-                    }
-                }
-            }
+        final ProviderInfo provider = mContext.getPackageManager().resolveContentProvider(
+                authority, PackageManager.ComponentInfoFlags.of(PackageManager.MATCH_SYSTEM_ONLY));
+        if (provider == null) {
+            Log.i(TAG, "could not find provider");
+            return null;
+        }
+        if (authority.equals(provider.authority) && isSystemApp(provider)) {
+            return authority;
         }
         Log.e(TAG, "authority not valid");
         return null;
diff --git a/src/com/android/settings/biometrics/fingerprint2/data/repository/FingerprintSensorRepository.kt b/src/com/android/settings/biometrics/fingerprint2/data/repository/FingerprintSensorRepository.kt
index 000a477..b7616e4 100644
--- a/src/com/android/settings/biometrics/fingerprint2/data/repository/FingerprintSensorRepository.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/data/repository/FingerprintSensorRepository.kt
@@ -32,6 +32,7 @@
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.callbackFlow
 import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.flow.transform
 import kotlinx.coroutines.withContext
 
 /**
@@ -45,12 +46,12 @@
 }
 
 class FingerprintSensorRepositoryImpl(
-    fingerprintManager: FingerprintManager,
-    backgroundDispatcher: CoroutineDispatcher,
-    activityScope: CoroutineScope,
+  fingerprintManager: FingerprintManager,
+  backgroundDispatcher: CoroutineDispatcher,
+  activityScope: CoroutineScope,
 ) : FingerprintSensorRepository {
 
-  override val fingerprintSensor: Flow<FingerprintSensor> =
+  private val fingerprintPropsInternal: Flow<FingerprintSensorPropertiesInternal> =
     callbackFlow {
         val callback =
           object : IFingerprintAuthenticatorsRegisteredCallback.Stub() {
@@ -60,7 +61,7 @@
               if (sensors.isEmpty()) {
                 trySend(DEFAULT_PROPS)
               } else {
-                trySend(sensors[0].toFingerprintSensor())
+                trySend(sensors[0])
               }
             }
           }
@@ -71,20 +72,24 @@
       }
       .stateIn(activityScope, started = SharingStarted.Eagerly, initialValue = DEFAULT_PROPS)
 
-    companion object {
-        private const val TAG = "FingerprintSensorRepoImpl"
-
-        private val DEFAULT_PROPS =
-            FingerprintSensorPropertiesInternal(
-                -1 /* sensorId */,
-                SensorProperties.STRENGTH_CONVENIENCE,
-                0 /* maxEnrollmentsPerUser */,
-                listOf<ComponentInfoInternal>(),
-                FingerprintSensorProperties.TYPE_UNKNOWN,
-                false /* halControlsIllumination */,
-                true /* resetLockoutRequiresHardwareAuthToken */,
-                listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
-            )
-                .toFingerprintSensor()
+  override val fingerprintSensor: Flow<FingerprintSensor> =
+    fingerprintPropsInternal.transform {
+      emit(it.toFingerprintSensor())
     }
+
+  companion object {
+    private const val TAG = "FingerprintSensorRepoImpl"
+
+    private val DEFAULT_PROPS =
+      FingerprintSensorPropertiesInternal(
+        -1 /* sensorId */,
+        SensorProperties.STRENGTH_CONVENIENCE,
+        0 /* maxEnrollmentsPerUser */,
+        listOf<ComponentInfoInternal>(),
+        FingerprintSensorProperties.TYPE_UNKNOWN,
+        false /* halControlsIllumination */,
+        true /* resetLockoutRequiresHardwareAuthToken */,
+        listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
+      )
+  }
 }
diff --git a/src/com/android/settings/biometrics/fingerprint2/domain/interactor/FingerprintManagerInteractorImpl.kt b/src/com/android/settings/biometrics/fingerprint2/domain/interactor/FingerprintManagerInteractorImpl.kt
index 900f7cf..652bc0c 100644
--- a/src/com/android/settings/biometrics/fingerprint2/domain/interactor/FingerprintManagerInteractorImpl.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/domain/interactor/FingerprintManagerInteractorImpl.kt
@@ -20,10 +20,12 @@
 import android.content.Intent
 import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricFingerprintConstants
+import android.hardware.biometrics.SensorLocationInternal
 import android.hardware.fingerprint.FingerprintEnrollOptions;
 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
diff --git a/src/com/android/settings/biometrics/fingerprint2/lib/domain/interactor/FingerprintManagerInteractor.kt b/src/com/android/settings/biometrics/fingerprint2/lib/domain/interactor/FingerprintManagerInteractor.kt
index c0e1b4a..105929d 100644
--- a/src/com/android/settings/biometrics/fingerprint2/lib/domain/interactor/FingerprintManagerInteractor.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/lib/domain/interactor/FingerprintManagerInteractor.kt
@@ -16,6 +16,7 @@
 
 package com.android.settings.biometrics.fingerprint2.lib.domain.interactor
 
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
 import com.android.settings.biometrics.fingerprint2.lib.model.EnrollReason
 import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
 import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintAuthAttemptModel
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/rfps/ui/fragment/RFPSEnrollFragment.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/rfps/ui/fragment/RFPSEnrollFragment.kt
index a9cd16f..f6917f3 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/rfps/ui/fragment/RFPSEnrollFragment.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/rfps/ui/fragment/RFPSEnrollFragment.kt
@@ -33,7 +33,6 @@
 import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.settings.R
-import com.android.settings.biometrics.fingerprint2.domain.interactor.OrientationInteractor
 import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
 import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.viewmodel.RFPSIconTouchViewModel
 import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.viewmodel.RFPSViewModel
@@ -42,7 +41,6 @@
 import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.widget.RFPSProgressBar
 import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.BackgroundViewModel
 import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
-import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment
 import com.google.android.setupcompat.template.FooterBarMixin
 import com.google.android.setupcompat.template.FooterButton
@@ -86,6 +84,7 @@
   private val backgroundViewModel: BackgroundViewModel by lazy {
     viewModelProvider[BackgroundViewModel::class.java]
   }
+
   override fun onCreateView(
     inflater: LayoutInflater,
     container: ViewGroup?,
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/rfps/ui/widget/RFPSProgressBar.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/rfps/ui/widget/RFPSProgressBar.kt
index 5a6fc14..dd7d9f5 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/rfps/ui/widget/RFPSProgressBar.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/rfps/ui/widget/RFPSProgressBar.kt
@@ -24,7 +24,6 @@
 import android.graphics.drawable.Drawable
 import android.graphics.drawable.LayerDrawable
 import android.util.AttributeSet
-import android.util.Log
 import android.view.animation.AnimationUtils
 import android.view.animation.Interpolator
 import com.android.settings.R
@@ -82,7 +81,6 @@
     }
 
     shouldAnimateInternal = shouldAnimate
-
   }
   /** This function should only be called when actual progress has been made. */
   fun updateProgress(percentComplete: Float) {
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/fragment/UdfpsEnrollFragment.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/fragment/UdfpsEnrollFragment.kt
index 6145128..9dfc222 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/fragment/UdfpsEnrollFragment.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/fragment/UdfpsEnrollFragment.kt
@@ -17,8 +17,9 @@
 package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.fragment
 
 import android.os.Bundle
-import android.util.Log
 import android.view.View
+import android.view.WindowManager
+import android.widget.TextView
 import androidx.annotation.VisibleForTesting
 import androidx.fragment.app.Fragment
 import androidx.lifecycle.Lifecycle
@@ -28,19 +29,31 @@
 import com.airbnb.lottie.LottieAnimationView
 import com.airbnb.lottie.LottieCompositionFactory
 import com.android.settings.R
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.DescriptionText
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.HeaderText
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.EducationAnimationModel
 import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.StageViewModel
 import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.UdfpsViewModel
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.widget.UdfpsEnrollViewV2
 import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
 import com.google.android.setupdesign.GlifLayout
-import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
 
+/** This fragment is responsible for showing the udfps Enrollment UI. */
 class UdfpsEnrollFragment() : Fragment(R.layout.fingerprint_v2_udfps_enroll_enrolling) {
 
   /** Used for testing purposes */
   private var factory: ViewModelProvider.Factory? = null
   private val viewModel: UdfpsViewModel by lazy { viewModelProvider[UdfpsViewModel::class.java] }
+  private lateinit var udfpsEnrollView: UdfpsEnrollViewV2
+
+  private val viewModelProvider: ViewModelProvider by lazy {
+    if (factory != null) {
+      ViewModelProvider(requireActivity(), factory!!)
+    } else {
+      ViewModelProvider(requireActivity())
+    }
+  }
 
   @VisibleForTesting
   constructor(theFactory: ViewModelProvider.Factory) : this() {
@@ -49,38 +62,73 @@
 
   override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
     super.onViewCreated(view, savedInstanceState)
-    val layout = view as GlifLayout
-    val illustrationLottie: LottieAnimationView = layout.findViewById(R.id.illustration_lottie)!!
+    val illustrationLottie: LottieAnimationView = view.findViewById(R.id.illustration_lottie)!!
+    udfpsEnrollView = view.findViewById(R.id.udfps_animation_view)!!
+    val titleTextView = view.findViewById<TextView>(R.id.title)!!
+    val descriptionTextView = view.findViewById<TextView>(R.id.description)!!
+
+    val glifLayout = view.findViewById<GlifLayout>(R.id.dummy_glif_layout)!!
+    val backgroundColor = glifLayout.backgroundBaseColor
+    val window = requireActivity().window
+    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
+    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
+    val color = backgroundColor?.defaultColor ?: glifLayout.primaryColor.defaultColor
+    window.statusBarColor = color
+    view.setBackgroundColor(color)
 
     viewLifecycleOwner.lifecycleScope.launch {
       repeatOnLifecycle(Lifecycle.State.RESUMED) {
         viewLifecycleOwner.lifecycleScope.launch {
-          viewModel.stageFlow.collect {
-            layout.setHeaderText(getHeaderText(it))
-            getDescriptionText(it)?.let { descriptionText ->
-              layout.setDescriptionText(descriptionText)
-            }
-            getLottie(it)?.let { lottie ->
-              layout.descriptionText = ""
-              LottieCompositionFactory.fromRawRes(requireContext().applicationContext, lottie)
-                .addListener { comp ->
-                  comp?.let { composition ->
-                    viewLifecycleOwner.lifecycleScope.launch {
-                        illustrationLottie.setComposition(composition)
-                        illustrationLottie.visibility = View.VISIBLE
-                        illustrationLottie.playAnimation()
-                      }
-                  }
-                }
+          viewModel.headerText.collect { titleTextView.setText(it.toResource()) }
+        }
+
+        viewLifecycleOwner.lifecycleScope.launch {
+          viewModel.descriptionText.collect {
+            if (it != null) {
+              it.toResource()?.let { text -> descriptionTextView.setText(text) }
+            } else {
+              descriptionTextView.text = ""
             }
           }
         }
+
+        viewLifecycleOwner.lifecycleScope.launch {
+          viewModel.sensorLocation.collect { rect -> udfpsEnrollView.setSensorRect(rect) }
+        }
+
+        viewLifecycleOwner.lifecycleScope.launch {
+          viewModel.accessibilityEnabled.collect { isEnabled -> udfpsEnrollView.setAccessibilityEnabled(isEnabled) }
+        }
+
+        viewLifecycleOwner.lifecycleScope.launch {
+          viewModel.lottie.collect { lottieModel ->
+            val resource = lottieModel.toResource()
+            if (resource != null) {
+              LottieCompositionFactory.fromRawRes(requireContext(), resource).addListener { comp ->
+                comp?.let { composition ->
+                  illustrationLottie.setComposition(composition)
+                  illustrationLottie.visibility = View.VISIBLE
+                  illustrationLottie.playAnimation()
+                }
+              }
+            } else {
+              illustrationLottie.visibility = View.INVISIBLE
+            }
+          }
+        }
+        viewLifecycleOwner.lifecycleScope.launch {
+          viewModel.udfpsEvent.collect { udfpsEnrollView.onUdfpsEvent(it) }
+        }
+
+        viewLifecycleOwner.lifecycleScope.launch {
+          viewModel.enrollStage.collect { udfpsEnrollView.updateStage(it) }
+        }
       }
     }
   }
 
-  private fun getHeaderText(stageViewModel: StageViewModel): Int {
-    return when (stageViewModel) {
+  private fun HeaderText.toResource(): Int {
+    return when (this.stageViewModel) {
       StageViewModel.Center,
       StageViewModel.Guided,
       StageViewModel.Fingertip,
@@ -90,8 +138,8 @@
     }
   }
 
-  private fun getDescriptionText(stageViewModel: StageViewModel): Int? {
-    return when (stageViewModel) {
+  private fun DescriptionText.toResource(): Int? {
+    return when (this.stageViewModel) {
       StageViewModel.Center,
       StageViewModel.Guided,
       StageViewModel.Fingertip,
@@ -101,8 +149,8 @@
     }
   }
 
-  private fun getLottie(stageViewModel: StageViewModel): Int? {
-    return when (stageViewModel) {
+  private fun EducationAnimationModel.toResource(): Int? {
+    return when (this.stageViewModel) {
       StageViewModel.Center,
       StageViewModel.Guided -> R.raw.udfps_center_hint_lottie
       StageViewModel.Fingertip -> R.raw.udfps_tip_hint_lottie
@@ -112,14 +160,6 @@
     }
   }
 
-  private val viewModelProvider: ViewModelProvider by lazy {
-    if (factory != null) {
-      ViewModelProvider(requireActivity(), factory!!)
-    } else {
-      ViewModelProvider(requireActivity())
-    }
-  }
-
   companion object {
     private const val TAG = "UDFPSEnrollFragment"
     private val navStep = FingerprintNavigationStep.Enrollment::class
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/DescriptionText.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/DescriptionText.kt
new file mode 100644
index 0000000..192a787
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/DescriptionText.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel
+
+/** Represents the description text for UDFPS enrollment */
+data class DescriptionText(
+  val isSuw: Boolean,
+  val isAccessibility: Boolean,
+  val stageViewModel: StageViewModel,
+)
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/EducationAnimationModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/EducationAnimationModel.kt
new file mode 100644
index 0000000..cf125c3
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/EducationAnimationModel.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel
+
+/** Represents the lottie for UDFPS enrollment */
+data class EducationAnimationModel(
+  val isSuw: Boolean,
+  val isAccessibility: Boolean,
+  val stageViewModel: StageViewModel,
+)
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/HeaderText.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/HeaderText.kt
new file mode 100644
index 0000000..9cfcddc
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/HeaderText.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel
+
+/** Represents the header text for UDFPS enrollment */
+data class HeaderText(
+  val isSuw: Boolean,
+  val isAccessibility: Boolean,
+  val stageViewModel: StageViewModel,
+)
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/StageViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/StageViewModel.kt
index b879ce1..75eaec7 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/StageViewModel.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/StageViewModel.kt
@@ -22,15 +22,30 @@
  * of the where the user should press their fingerprint
  */
 sealed class StageViewModel {
+  /** Unknown stage */
   data object Unknown : StageViewModel()
 
+  /** This is the stage that moves the fingerprint icon around during enrollment. */
   data object Guided : StageViewModel()
 
+  /** The center stage is the initial stage of enrollment. */
   data object Center : StageViewModel()
 
+  /**
+   * Fingerprint stage of enrollment. Typically there is some sort of indication that a user should
+   * be using their finger tip to enroll.
+   */
   data object Fingertip : StageViewModel()
 
+  /**
+   * Left edge stage of enrollment. Typically there is an indication that a user should be using the
+   * left edge of their fingerprint.
+   */
   data object LeftEdge : StageViewModel()
 
+  /**
+   * Right edge stage of enrollment. Typically there is an indication that a user should be using
+   * the right edge of their fingerprint.
+   */
   data object RightEdge : StageViewModel()
 }
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsEnrollEvent.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsEnrollEvent.kt
new file mode 100644
index 0000000..e349ceb
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsEnrollEvent.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel
+
+/** A class indicating a udfps enroll event occurred. */
+sealed class UdfpsEnrollEvent
+
+/** Describes how many [remainingSteps] and how many [totalSteps] are left in udfps enrollment. */
+data class UdfpsProgress(val remainingSteps: Int, val totalSteps: Int) : UdfpsEnrollEvent()
+
+/** Indicates a help event has been sent by enrollment */
+data class UdfpsHelp(val helpMsgId: Int, val helpString: String) : UdfpsEnrollEvent()
+
+/** Indicates a error event has been sent by enrollment */
+data class UdfpsError(val errMsgId: Int, val errString: String) : UdfpsEnrollEvent()
+
+/** Indicates an acquired event has occurred */
+data class Acquired(val acquiredGood: Boolean) : UdfpsEnrollEvent()
+
+/** Indicates a pointer down event has occurred */
+data object PointerDown : UdfpsEnrollEvent()
+
+/** Indicates a pointer up event has occurred */
+data object PointerUp : UdfpsEnrollEvent()
+
+/** Indicates the overlay has shown */
+data object OverlayShown : UdfpsEnrollEvent()
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsViewModel.kt
index 4fc3d1c..a5fdf1c 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsViewModel.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsViewModel.kt
@@ -16,16 +16,93 @@
 
 package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel
 
+import android.graphics.Rect
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
 import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.flow
 import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
 
 /** ViewModel used to drive UDFPS Enrollment through [UdfpsEnrollFragment] */
 class UdfpsViewModel() : ViewModel() {
 
-  /** Indicates what stage UDFPS enrollment is in. */
-  val stageFlow = flowOf(StageViewModel.Center)
+  private val isSetupWizard = flowOf(false)
+
+  /** Indicates which Enrollment stage we are currently in. */
+  private val sensorLocationInternal = Pair(540, 1713)
+  private val sensorRadius = 100
+  private val sensorRect =
+    Rect(
+      this.sensorLocationInternal.first - sensorRadius,
+      this.sensorLocationInternal.second - sensorRadius,
+      this.sensorLocationInternal.first + sensorRadius,
+      this.sensorLocationInternal.second + sensorRadius,
+    )
+
+  private val stageThresholds = flowOf(listOf(.25, .5, .75, .875))
+
+  /** Indicates if accessibility is enabled */
+  val accessibilityEnabled = flowOf(false)
+
+  /** Indicates the locates of the fingerprint sensor. */
+  val sensorLocation: Flow<Rect> = flowOf(sensorRect)
+
+  /** This is currently not hooked up to fingerprint manager, and is being fed mock events. */
+  val udfpsEvent: Flow<UdfpsEnrollEvent> =
+    flow {
+        enrollEvents.forEach { events ->
+          events.forEach { event -> emit(event) }
+          delay(1000)
+        }
+      }
+      .flowOn(Dispatchers.IO)
+
+  /** Determines the current [StageViewModel] enrollment is in */
+  val enrollStage: Flow<StageViewModel> =
+    combine(stageThresholds, udfpsEvent) { thresholds, event ->
+        if (event is UdfpsProgress) {
+          thresholdToStageMap(thresholds, event.totalSteps - event.remainingSteps, event.totalSteps)
+        } else {
+          null
+        }
+      }
+      .filterNotNull()
+
+  /** The header text for UDFPS enrollment */
+  val headerText: Flow<HeaderText> =
+    combine(isSetupWizard, accessibilityEnabled, enrollStage) { isSuw, isAccessibility, stage ->
+      return@combine HeaderText(isSuw, isAccessibility, stage)
+    }
+
+  private val shouldClearDescriptionText = enrollStage.map { it is StageViewModel.Unknown }
+
+  /** The description text for UDFPS enrollment */
+  val descriptionText: Flow<DescriptionText?> =
+    combine(isSetupWizard, accessibilityEnabled, enrollStage, shouldClearDescriptionText) {
+      isSuw,
+      isAccessibility,
+      stage,
+      shouldClearText ->
+      if (shouldClearText) {
+        return@combine null
+      } else {
+        return@combine DescriptionText(isSuw, isAccessibility, stage)
+      }
+    }
+
+  /** The lottie that should be shown for UDFPS Enrollment */
+  val lottie: Flow<EducationAnimationModel> =
+    combine(isSetupWizard, accessibilityEnabled, enrollStage) { isSuw, isAccessibility, stage ->
+      return@combine EducationAnimationModel(isSuw, isAccessibility, stage)
+    }.distinctUntilChanged()
 
   class UdfpsEnrollmentFactory() : ViewModelProvider.Factory {
 
@@ -38,5 +115,58 @@
   companion object {
     private val navStep = FingerprintNavigationStep.Enrollment::class
     private const val TAG = "UDFPSViewModel"
+    private val ENROLLMENT_STAGES_ORDERED =
+      listOf(
+        StageViewModel.Center,
+        StageViewModel.Guided,
+        StageViewModel.Fingertip,
+        StageViewModel.LeftEdge,
+        StageViewModel.RightEdge,
+      )
+
+    /**
+     * [thresholds] is a list of 4 numbers from [0,1] that separate enrollment into 5 stages. The
+     * stage is determined by mapping [thresholds] * [maxSteps] and finding where the [currentStep]
+     * is.
+     *
+     * Each number in the array should be strictly increasing such as [0.2, 0.5, 0.6, 0.8]
+     */
+    private fun thresholdToStageMap(
+      thresholds: List<Double>,
+      currentStep: Int,
+      maxSteps: Int,
+    ): StageViewModel {
+      val stageIterator = ENROLLMENT_STAGES_ORDERED.iterator()
+      thresholds.forEach {
+        val thresholdLimit = it * maxSteps
+        val curr = stageIterator.next()
+        if (currentStep < thresholdLimit) {
+          return curr
+        }
+      }
+      return stageIterator.next()
+    }
+
+    /** This will be removed */
+    private val enrollEvents: List<List<UdfpsEnrollEvent>> =
+      listOf(
+        listOf(OverlayShown),
+        CreateProgress(10, 10),
+        CreateProgress(9, 10),
+        CreateProgress(8, 10),
+        CreateProgress(7, 10),
+        CreateProgress(6, 10),
+        CreateProgress(5, 10),
+        CreateProgress(4, 10),
+        CreateProgress(3, 10),
+        CreateProgress(2, 10),
+        CreateProgress(1, 10),
+        CreateProgress(0, 10),
+      )
+
+    /** This will be removed */
+    private fun CreateProgress(remaining: Int, total: Int): List<UdfpsEnrollEvent> {
+      return listOf(PointerDown, Acquired(true), UdfpsProgress(remaining, total), PointerUp)
+    }
   }
 }
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/widget/UdfpsEnrollHelperV2.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/widget/UdfpsEnrollHelperV2.kt
new file mode 100644
index 0000000..5d4607c4
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/widget/UdfpsEnrollHelperV2.kt
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.widget
+
+import android.content.Context
+import android.graphics.PointF
+import android.util.TypedValue
+import android.view.accessibility.AccessibilityManager
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.StageViewModel
+
+/** Keeps track of which guided enrollment point we should be using */
+class UdfpsEnrollHelperV2(private val mContext: Context) {
+
+  private var isGuidedEnrollment: Boolean = false
+  private val accessibilityEnabled: Boolean
+  private val guidedEnrollmentPoints: MutableList<PointF>
+  private var index = 0
+
+  init {
+    val am = mContext.getSystemService(AccessibilityManager::class.java)
+    accessibilityEnabled = am!!.isEnabled
+    guidedEnrollmentPoints = ArrayList()
+
+    // Number of pixels per mm
+    val px =
+      TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 1f, mContext.resources.displayMetrics)
+    guidedEnrollmentPoints.add(PointF(2.00f * px, 0.00f * px))
+    guidedEnrollmentPoints.add(PointF(0.87f * px, -2.70f * px))
+    guidedEnrollmentPoints.add(PointF(-1.80f * px, -1.31f * px))
+    guidedEnrollmentPoints.add(PointF(-1.80f * px, 1.31f * px))
+    guidedEnrollmentPoints.add(PointF(0.88f * px, 2.70f * px))
+    guidedEnrollmentPoints.add(PointF(3.94f * px, -1.06f * px))
+    guidedEnrollmentPoints.add(PointF(2.90f * px, -4.14f * px))
+    guidedEnrollmentPoints.add(PointF(-0.52f * px, -5.95f * px))
+    guidedEnrollmentPoints.add(PointF(-3.33f * px, -3.33f * px))
+    guidedEnrollmentPoints.add(PointF(-3.99f * px, -0.35f * px))
+    guidedEnrollmentPoints.add(PointF(-3.62f * px, 2.54f * px))
+    guidedEnrollmentPoints.add(PointF(-1.49f * px, 5.57f * px))
+    guidedEnrollmentPoints.add(PointF(2.29f * px, 4.92f * px))
+    guidedEnrollmentPoints.add(PointF(3.82f * px, 1.78f * px))
+  }
+
+  /**
+   * This indicates whether we should be offsetting the enrollment icon based on
+   * [guidedEnrollmentPoints]
+   */
+  fun onUpdateStage(stage: StageViewModel) {
+    this.isGuidedEnrollment = stage is StageViewModel.Guided
+  }
+
+  /** Updates [index] to be used by [guidedEnrollmentPoints] */
+  fun onEnrollmentProgress(remaining: Int, totalSteps: Int) {
+    index = totalSteps - remaining
+  }
+
+  /**
+   * Returns the current guided enrollment point, or (0,0) if we are not in guided enrollment or are
+   * in accessibility.
+   */
+  val guidedEnrollmentLocation: PointF?
+    get() {
+      if (accessibilityEnabled || !isGuidedEnrollment) {
+        return null
+      }
+      var scale = SCALE
+      val originalPoint = guidedEnrollmentPoints[index % guidedEnrollmentPoints.size]
+      return PointF(originalPoint.x * scale, originalPoint.y * scale)
+    }
+
+  companion object {
+    private const val TAG = "UdfpsEnrollHelperV2"
+    private const val SCALE = 0.5f
+  }
+}
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/widget/UdfpsEnrollIconV2.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/widget/UdfpsEnrollIconV2.kt
new file mode 100644
index 0000000..3b48140
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/widget/UdfpsEnrollIconV2.kt
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.widget
+
+import android.animation.AnimatorSet
+import android.animation.ValueAnimator
+import android.annotation.ColorInt
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.ColorFilter
+import android.graphics.Paint
+import android.graphics.PixelFormat
+import android.graphics.Rect
+import android.graphics.RectF
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.ShapeDrawable
+import android.graphics.drawable.shapes.PathShape
+import android.util.AttributeSet
+import android.util.Log
+import android.util.PathParser
+import android.view.animation.AccelerateDecelerateInterpolator
+import androidx.core.animation.addListener
+import androidx.core.graphics.toRect
+import androidx.core.graphics.toRectF
+import com.android.settings.R
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.StageViewModel
+import kotlin.math.sin
+
+/**
+ * This class is responsible for drawing the udfps icon, and to update its movement based on the
+ * various stages of enrollment
+ */
+class UdfpsEnrollIconV2 internal constructor(context: Context, attrs: AttributeSet?) : Drawable() {
+  private var targetAnimatorSet: AnimatorSet? = null
+  private val movingTargetFpIcon: Drawable
+  private val fingerprintDrawable: ShapeDrawable
+  private val sensorOutlinePaint: Paint
+  private val blueFill: Paint
+  private val helper = UdfpsEnrollHelperV2(context)
+  @ColorInt private var enrollIconColor = 0
+  @ColorInt private var movingTargetFill = 0
+  private var currentScale = 1.0f
+  private var alpha = 0
+
+  /**
+   * This is the physical location of the sensor. This rect will be updated by [drawSensorRectAt]
+   */
+  private val sensorRectBounds: Rect = Rect()
+
+  /**
+   * The following values are used to describe where the icon should be drawn. [currX] and [currY]
+   * are changed based on the current guided enrollment step which is given by the
+   * [UdfpsEnrollHelperV2]
+   */
+  private var currX = 0f
+  private var currY = 0f
+
+  private var sensorWidth = 0f
+  private var sensorHeight = 0f
+
+  init {
+    fingerprintDrawable = createUdfpsIcon(context)
+    context
+      .obtainStyledAttributes(
+        attrs,
+        R.styleable.BiometricsEnrollView,
+        R.attr.biometricsEnrollStyle,
+        R.style.BiometricsEnrollStyle,
+      )
+      .let {
+        enrollIconColor = it.getColor(R.styleable.BiometricsEnrollView_biometricsEnrollIcon, 0)
+        movingTargetFill =
+          it.getColor(R.styleable.BiometricsEnrollView_biometricsMovingTargetFill, 0)
+        it.recycle()
+      }
+
+    sensorOutlinePaint = Paint(0 /* flags */).apply {
+      isAntiAlias = true
+      setColor(movingTargetFill)
+      style = Paint.Style.FILL
+    }
+
+    blueFill = Paint(0 /* flags */).apply {
+      isAntiAlias = true
+      setColor(movingTargetFill)
+      style = Paint.Style.FILL
+    }
+
+    movingTargetFpIcon = context.resources.getDrawable(R.drawable.ic_enrollment_fingerprint, null).apply {
+      setTint(enrollIconColor)
+      mutate()
+    }
+
+    fingerprintDrawable.setTint(enrollIconColor)
+    setAlpha(255)
+  }
+
+  override fun getAlpha(): Int {
+    return alpha
+  }
+
+  override fun setColorFilter(colorFilter: ColorFilter?) {}
+
+  override fun getOpacity(): Int {
+    return PixelFormat.UNKNOWN
+  }
+
+  override fun setAlpha(alpha: Int) {
+    this.alpha = alpha
+  }
+
+  /**
+   * The [sensorRect] coordinates for the sensor area. The [sensorRect] should be the coordinates
+   * with respect to its root frameview
+   */
+  fun drawSensorRectAt(sensorRect: Rect) {
+    Log.e(TAG, "UdfpsEnrollIcon#drawSensorRect($sensorRect)")
+    sensorRectBounds.set(sensorRect)
+    fingerprintDrawable.bounds = sensorRect
+    movingTargetFpIcon.bounds = sensorRect
+    currX = sensorRect.left.toFloat()
+    currY = sensorRect.top.toFloat()
+    sensorWidth = (sensorRect.right - sensorRect.left).toFloat()
+    sensorHeight = (sensorRect.bottom - sensorRect.top).toFloat()
+    invalidateSelf()
+  }
+
+  /** Update the progress of the icon */
+  fun onEnrollmentProgress(remaining: Int, totalSteps: Int) {
+    helper.onEnrollmentProgress(remaining, totalSteps)
+    val offset = helper.guidedEnrollmentLocation
+    val currentBounds = getCurrLocation().toRect()
+    if (offset != null) {
+      // This is the desired location of the sensor rect, the [EnrollHelper]
+      // offsets the initial sensor rect by a bit to get the user to move their finger a bit more.
+      val targetRect = Rect(sensorRectBounds).toRectF()
+      targetRect.offset(offset.x, offset.y)
+      var shouldAnimateMovement =
+        !currentBounds.equals(targetRect) && offset.x != 0f && offset.y != 0f
+      if (shouldAnimateMovement) {
+        targetAnimatorSet?.let { it.cancel() }
+        animateMovement(currentBounds, targetRect, true)
+      }
+    } else {
+      // If we are not offsetting the sensor, move it back to its original place
+      animateMovement(currentBounds, sensorRectBounds.toRectF(), false)
+    }
+
+    invalidateSelf()
+  }
+
+  /** Update the stage of the icon */
+  fun updateStage(it: StageViewModel) {
+    helper.onUpdateStage(it)
+    invalidateSelf()
+  }
+
+  override fun draw(canvas: Canvas) {
+    val currLocation = getCurrLocation()
+    canvas.scale(currentScale, currentScale, currLocation.centerX(), currLocation.centerY())
+
+    sensorRectBounds?.let { canvas.drawOval(currLocation, sensorOutlinePaint) }
+    fingerprintDrawable.bounds = currLocation.toRect()
+    fingerprintDrawable.draw(canvas)
+    fingerprintDrawable.setAlpha(alpha)
+    sensorOutlinePaint.setAlpha(alpha)
+  }
+
+  private fun getCurrLocation(): RectF =
+    RectF(currX, currY, currX + sensorWidth, currY + sensorHeight)
+
+  private fun animateMovement(currentBounds: Rect, offsetRect: RectF, scaleMovement: Boolean) {
+    if (currentBounds.equals(offsetRect)) {
+      return
+    }
+    val xAnimator = ValueAnimator.ofFloat(currentBounds.left.toFloat(), offsetRect.left)
+    xAnimator.addUpdateListener {
+      currX = it.animatedValue as Float
+      invalidateSelf()
+    }
+
+    val yAnimator = ValueAnimator.ofFloat(currentBounds.top.toFloat(), offsetRect.top)
+    yAnimator.addUpdateListener {
+      currY = it.animatedValue as Float
+      invalidateSelf()
+    }
+    val animators = mutableListOf(xAnimator, yAnimator)
+    val duration = TARGET_ANIM_DURATION_LONG
+    if (scaleMovement) {
+      val scaleAnimator = ValueAnimator.ofFloat(0f, Math.PI.toFloat())
+      scaleAnimator.setDuration(duration)
+      scaleAnimator.addUpdateListener { animation: ValueAnimator ->
+        // Grow then shrink
+        currentScale =
+          (1 + SCALE_MAX * sin((animation.getAnimatedValue() as Float).toDouble()).toFloat())
+        invalidateSelf()
+      }
+      scaleAnimator.addListener(onEnd = { currentScale = 1f })
+      animators.add(scaleAnimator)
+    }
+
+    targetAnimatorSet = AnimatorSet()
+
+    targetAnimatorSet?.let {
+      it.interpolator = AccelerateDecelerateInterpolator()
+      it.setDuration(duration)
+      it.playTogether(animators.toList())
+      it.start()
+    }
+  }
+
+  companion object {
+    private const val TAG = "UdfpsEnrollDrawableV2"
+    private const val DEFAULT_STROKE_WIDTH = 3f
+    private const val TARGET_ANIM_DURATION_LONG = 800L
+    private const val SCALE_MAX = 0.25f
+
+    private fun createUdfpsIcon(context: Context): ShapeDrawable {
+      val fpPath = context.resources.getString(R.string.config_udfpsIcon)
+      val drawable = ShapeDrawable(PathShape(PathParser.createPathFromPathData(fpPath), 72f, 72f)).apply {
+        mutate()
+        paint.style = Paint.Style.STROKE
+        paint.strokeCap = Paint.Cap.ROUND
+        paint.strokeWidth = DEFAULT_STROKE_WIDTH
+      }
+      return drawable
+    }
+  }
+}
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/widget/UdfpsEnrollProgressBarDrawableV2.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/widget/UdfpsEnrollProgressBarDrawableV2.kt
new file mode 100644
index 0000000..e5f89cb
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/widget/UdfpsEnrollProgressBarDrawableV2.kt
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.widget
+
+import android.animation.ValueAnimator
+import android.animation.ValueAnimator.AnimatorUpdateListener
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.ColorFilter
+import android.graphics.Paint
+import android.graphics.PixelFormat
+import android.graphics.Rect
+import android.graphics.drawable.Drawable
+import android.os.Process
+import android.os.VibrationAttributes
+import android.os.VibrationEffect
+import android.os.Vibrator
+import android.util.AttributeSet
+import android.util.DisplayMetrics
+import android.view.animation.DecelerateInterpolator
+import android.view.animation.Interpolator
+import androidx.annotation.ColorInt
+import androidx.core.graphics.toRectF
+import com.android.internal.annotations.VisibleForTesting
+import com.android.settings.R
+import kotlin.math.max
+import kotlin.math.min
+
+/**
+ * UDFPS enrollment progress bar. This view is responsible for drawing the progress ring and its
+ * fill around the center of the UDFPS sensor.
+ */
+class UdfpsEnrollProgressBarDrawableV2(private val mContext: Context, attrs: AttributeSet?) :
+  Drawable() {
+  private val sensorRect: Rect = Rect()
+  private val strokeWidthPx: Float
+
+  @ColorInt private val progressColor: Int
+  @ColorInt private var helpColor: Int = 0
+  @ColorInt private val onFirstBucketFailedColor: Int
+
+  private val backgroundPaint: Paint
+
+  @VisibleForTesting val fillPaint: Paint
+  private val vibrator: Vibrator
+  private var isAccessibilityEnabled: Boolean = false
+  private var afterFirstTouch = false
+  private var remainingSteps = 0
+  private var totalSteps = 0
+  private var progress = 0f
+  private var progressAnimator: ValueAnimator? = null
+  private val progressUpdateListener: AnimatorUpdateListener
+  private var showingHelp = false
+  private var fillColorAnimator: ValueAnimator? = null
+  private val fillColorUpdateListener: AnimatorUpdateListener
+  private var backgroundColorAnimator: ValueAnimator? = null
+  private val backgroundColorUpdateListener: AnimatorUpdateListener
+  private var complete = false
+  private var movingTargetFill = 0
+  private var movingTargetFillError = 0
+  private var enrollProgressColor = 0
+  private var enrollProgressHelp = 0
+  private var enrollProgressHelpWithTalkback = 0
+  private val progressBarRadius: Int
+
+  init {
+    val ta =
+      mContext.obtainStyledAttributes(
+        attrs,
+        R.styleable.BiometricsEnrollView,
+        R.attr.biometricsEnrollStyle,
+        R.style.BiometricsEnrollStyle,
+      )
+    movingTargetFill = ta.getColor(R.styleable.BiometricsEnrollView_biometricsMovingTargetFill, 0)
+    movingTargetFillError =
+      ta.getColor(R.styleable.BiometricsEnrollView_biometricsMovingTargetFillError, 0)
+    enrollProgressColor = ta.getColor(R.styleable.BiometricsEnrollView_biometricsEnrollProgress, 0)
+    enrollProgressHelp =
+      ta.getColor(R.styleable.BiometricsEnrollView_biometricsEnrollProgressHelp, 0)
+    enrollProgressHelpWithTalkback =
+      ta.getColor(R.styleable.BiometricsEnrollView_biometricsEnrollProgressHelpWithTalkback, 0)
+    ta.recycle()
+    val density = mContext.resources.displayMetrics.densityDpi.toFloat()
+    strokeWidthPx = STROKE_WIDTH_DP * (density / DisplayMetrics.DENSITY_DEFAULT)
+    progressColor = enrollProgressColor
+    onFirstBucketFailedColor = movingTargetFillError
+    updateHelpColor()
+    backgroundPaint = Paint().apply {
+      strokeWidth = strokeWidthPx
+      setColor(movingTargetFill)
+      isAntiAlias = true
+      style = Paint.Style.STROKE
+      strokeCap = Paint.Cap.ROUND
+    }
+
+    // Progress fill should *not* use the extracted system color.
+    fillPaint = Paint().apply {
+      strokeWidth = strokeWidthPx
+      setColor(progressColor)
+      isAntiAlias = true
+      style = Paint.Style.STROKE
+      strokeCap = Paint.Cap.ROUND
+    }
+    vibrator = mContext.getSystemService(Vibrator::class.java)!!
+
+    progressBarRadius = mContext.resources.getInteger(R.integer.config_udfpsEnrollProgressBar)
+
+    progressUpdateListener = AnimatorUpdateListener { animation: ValueAnimator ->
+      progress = animation.getAnimatedValue() as Float
+      invalidateSelf()
+    }
+    fillColorUpdateListener = AnimatorUpdateListener { animation: ValueAnimator ->
+      fillPaint.setColor(animation.getAnimatedValue() as Int)
+      invalidateSelf()
+    }
+    backgroundColorUpdateListener = AnimatorUpdateListener { animation: ValueAnimator ->
+      backgroundPaint.setColor(animation.getAnimatedValue() as Int)
+      invalidateSelf()
+    }
+  }
+
+  /** Indicates enrollment progress has occurred. */
+  fun onEnrollmentProgress(remaining: Int, totalSteps: Int) {
+    afterFirstTouch = true
+    updateState(remaining, totalSteps, false /* showingHelp */)
+  }
+
+  /** Indicates enrollment help has occurred. */
+  fun onEnrollmentHelp(remaining: Int, totalSteps: Int) {
+    updateState(remaining, totalSteps, true /* showingHelp */)
+  }
+
+  /** Indicates the last step was acquired. */
+  fun onLastStepAcquired() {
+    updateState(0, totalSteps, false /* showingHelp */)
+  }
+
+  override fun draw(canvas: Canvas) {
+
+    canvas.save()
+    // This takes the sensors bounding box and expands it by [progressBarRadius] in all directions
+    val sensorProgressRect = Rect(sensorRect)
+    sensorProgressRect.inset(
+      -progressBarRadius,
+      -progressBarRadius,
+      -progressBarRadius,
+      -progressBarRadius,
+    )
+
+    // Rotate -90 degrees to make the progress start from the top right and not the bottom
+    // right
+    canvas.rotate(
+      -90f,
+      sensorProgressRect.centerX().toFloat(),
+      sensorProgressRect.centerY().toFloat(),
+    )
+    if (progress < 1f) {
+      // Draw the background color of the progress circle.
+      canvas.drawArc(
+        sensorProgressRect.toRectF(),
+        0f /* startAngle */,
+        360f /* sweepAngle */,
+        false /* useCenter */,
+        backgroundPaint,
+      )
+    }
+    if (progress > 0f) {
+      // Draw the filled portion of the progress circle.
+      canvas.drawArc(
+        sensorProgressRect.toRectF(),
+        0f /* startAngle */,
+        360f * progress /* sweepAngle */,
+        false /* useCenter */,
+        fillPaint,
+      )
+    }
+    canvas.restore()
+  }
+
+  /** Do nothing here, we will control the alpha internally. */
+  override fun setAlpha(alpha: Int) {}
+
+  /** Do not apply color filters here for enrollment. */
+  override fun setColorFilter(colorFilter: ColorFilter?) {}
+
+  /** Legacy code, returning PixelFormat.UNKNOWN */
+  override fun getOpacity(): Int {
+    return PixelFormat.UNKNOWN
+  }
+  /**
+   * Draws the progress with locations [sensorLocationX] [sensorLocationY], note these must be with
+   * respect to the parent framelayout.
+   */
+  fun drawProgressAt(sensorRect: Rect) {
+    this.sensorRect.set(sensorRect)
+  }
+
+  /** Indicates if accessibility is enabled or not. */
+  fun setAccessibilityEnabled(enabled: Boolean) {
+    isAccessibilityEnabled = enabled
+    updateHelpColor()
+  }
+
+  private fun updateHelpColor() {
+    helpColor =
+      if (!isAccessibilityEnabled) {
+        enrollProgressHelp
+      } else {
+        enrollProgressHelpWithTalkback
+      }
+  }
+
+  private fun updateState(remainingSteps: Int, totalSteps: Int, showingHelp: Boolean) {
+    updateProgress(remainingSteps, totalSteps, showingHelp)
+    updateFillColor(showingHelp)
+  }
+
+  private fun updateProgress(remainingSteps: Int, totalSteps: Int, showingHelp: Boolean) {
+    if (this.remainingSteps == remainingSteps && this.totalSteps == totalSteps) {
+      return
+    }
+    if (this.showingHelp) {
+      if (vibrator != null && isAccessibilityEnabled) {
+        vibrator.vibrate(
+          Process.myUid(),
+          mContext.opPackageName,
+          VIBRATE_EFFECT_ERROR,
+          javaClass.getSimpleName() + "::onEnrollmentHelp",
+          FINGERPRINT_ENROLLING_SONFICATION_ATTRIBUTES,
+        )
+      }
+    } else {
+      // If the first touch is an error, remainingSteps will be -1 and the callback
+      // doesn't come from onEnrollmentHelp. If we are in the accessibility flow,
+      // we still would like to vibrate.
+      if (vibrator != null) {
+        if (remainingSteps == -1 && isAccessibilityEnabled) {
+          vibrator.vibrate(
+            Process.myUid(),
+            mContext.opPackageName,
+            VIBRATE_EFFECT_ERROR,
+            javaClass.getSimpleName() + "::onFirstTouchError",
+            FINGERPRINT_ENROLLING_SONFICATION_ATTRIBUTES,
+          )
+        } else if (remainingSteps != -1 && !isAccessibilityEnabled) {
+          vibrator.vibrate(
+            Process.myUid(),
+            mContext.opPackageName,
+            SUCCESS_VIBRATION_EFFECT,
+            javaClass.getSimpleName() + "::OnEnrollmentProgress",
+            HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES,
+          )
+        }
+      }
+    }
+    this.showingHelp = showingHelp
+    this.remainingSteps = remainingSteps
+    this.totalSteps = totalSteps
+    val progressSteps = max(0.0, (totalSteps - remainingSteps).toDouble()).toInt()
+
+    // If needed, add 1 to progress and total steps to account for initial touch.
+    val adjustedSteps = if (afterFirstTouch) progressSteps + 1 else progressSteps
+    val adjustedTotal = if (afterFirstTouch) this.totalSteps + 1 else this.totalSteps
+    val targetProgress =
+      min(1.0, (adjustedSteps.toFloat() / adjustedTotal.toFloat()).toDouble()).toFloat()
+    if (progressAnimator != null && progressAnimator!!.isRunning) {
+      progressAnimator!!.cancel()
+    }
+    progressAnimator =
+      ValueAnimator.ofFloat(progress, targetProgress).also {
+        it.setDuration(PROGRESS_ANIMATION_DURATION_MS)
+        it.addUpdateListener(progressUpdateListener)
+        it.start()
+      }
+    if (remainingSteps == 0) {
+      startCompletionAnimation()
+    } else if (remainingSteps > 0) {
+      rollBackCompletionAnimation()
+    }
+  }
+
+  private fun animateBackgroundColor() {
+    if (backgroundColorAnimator != null && backgroundColorAnimator!!.isRunning) {
+      backgroundColorAnimator!!.end()
+    }
+    backgroundColorAnimator =
+      ValueAnimator.ofArgb(backgroundPaint.color, onFirstBucketFailedColor).also {
+        it.setDuration(FILL_COLOR_ANIMATION_DURATION_MS)
+        it.repeatCount = 1
+        it.repeatMode = ValueAnimator.REVERSE
+        it.interpolator = DEACCEL
+        it.addUpdateListener(backgroundColorUpdateListener)
+        it.start()
+      }
+  }
+
+  private fun updateFillColor(showingHelp: Boolean) {
+    if (!afterFirstTouch && showingHelp) {
+      // If we are on the first touch, animate the background color
+      // instead of the progress color.
+      animateBackgroundColor()
+      return
+    }
+    if (fillColorAnimator != null && fillColorAnimator!!.isRunning) {
+      fillColorAnimator!!.end()
+    }
+    @ColorInt val targetColor = if (showingHelp) helpColor else progressColor
+    fillColorAnimator =
+      ValueAnimator.ofArgb(fillPaint.color, targetColor).also {
+        it.setDuration(FILL_COLOR_ANIMATION_DURATION_MS)
+        it.repeatCount = 1
+        it.repeatMode = ValueAnimator.REVERSE
+        it.interpolator = DEACCEL
+        it.addUpdateListener(fillColorUpdateListener)
+        it.start()
+      }
+  }
+
+  private fun startCompletionAnimation() {
+    if (complete) {
+      return
+    }
+    complete = true
+  }
+
+  private fun rollBackCompletionAnimation() {
+    if (!complete) {
+      return
+    }
+    complete = false
+  }
+
+  private fun loadResources(context: Context, attrs: AttributeSet?) {}
+
+  companion object {
+    private const val TAG = "UdfpsProgressBar"
+    private const val FILL_COLOR_ANIMATION_DURATION_MS = 350L
+    private const val PROGRESS_ANIMATION_DURATION_MS = 400L
+    private const val STROKE_WIDTH_DP = 12f
+    private val DEACCEL: Interpolator = DecelerateInterpolator()
+    private val VIBRATE_EFFECT_ERROR = VibrationEffect.createWaveform(longArrayOf(0, 5, 55, 60), -1)
+    private val FINGERPRINT_ENROLLING_SONFICATION_ATTRIBUTES =
+      VibrationAttributes.createForUsage(VibrationAttributes.USAGE_ACCESSIBILITY)
+    private val HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
+      VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK)
+    private val SUCCESS_VIBRATION_EFFECT = VibrationEffect.get(VibrationEffect.EFFECT_CLICK)
+  }
+}
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/widget/UdfpsEnrollViewV2.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/widget/UdfpsEnrollViewV2.kt
new file mode 100644
index 0000000..38bb024
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/widget/UdfpsEnrollViewV2.kt
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.widget
+
+import android.content.Context
+import android.graphics.Rect
+import android.util.AttributeSet
+import android.util.Log
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import android.widget.ImageView
+import com.android.settings.R
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.Acquired
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.OverlayShown
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.PointerDown
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.PointerUp
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.StageViewModel
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.UdfpsEnrollEvent
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.UdfpsError
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.UdfpsHelp
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.UdfpsProgress
+
+/**
+ * View corresponding with fingerprint_v2_udfps_enroll_view.xml. This view is responsible for
+ * drawing the [UdfpsEnrollIconV2] and the [UdfpsEnrollProgressBarDrawableV2].
+ */
+class UdfpsEnrollViewV2(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs) {
+  private var isAccessibilityEnabled: Boolean = false
+  private lateinit var sensorRect: Rect
+  private val fingerprintIcon: UdfpsEnrollIconV2 = UdfpsEnrollIconV2(mContext, attrs)
+  private val fingerprintProgressDrawable: UdfpsEnrollProgressBarDrawableV2 =
+    UdfpsEnrollProgressBarDrawableV2(mContext, attrs)
+  private var mTotalSteps = -1
+  private var mRemainingSteps = -1
+
+  /**
+   * This function computes the center (x,y) location with respect to the parent [FrameLayout] for
+   * the [UdfpsEnrollProgressBarDrawableV2]. It also computes the [Rect] with respect to the parent
+   * [FrameLayout] for the [UdfpsEnrollIconV2].
+   */
+  fun setSensorRect(rect: Rect) {
+    this.sensorRect = rect
+    post {
+      findViewById<ImageView?>(R.id.udfps_enroll_animation_fp_progress_view)?.also {
+        it.setImageDrawable(fingerprintProgressDrawable)
+      }
+      findViewById<ImageView>(R.id.udfps_enroll_animation_fp_view)?.also {
+        it.setImageDrawable(fingerprintIcon)
+      }
+      val parentView = parent as ViewGroup
+      val coords = parentView.getLocationOnScreen()
+      val parentLeft = coords[0]
+      val parentTop = coords[1]
+      val sensorRectOffset = Rect(sensorRect)
+      sensorRectOffset.offset(-parentLeft, -parentTop)
+
+      fingerprintIcon.drawSensorRectAt(sensorRectOffset)
+      fingerprintProgressDrawable.drawProgressAt(sensorRectOffset)
+    }
+  }
+
+  /** Updates the current enrollment stage. */
+  fun updateStage(it: StageViewModel) {
+    fingerprintIcon.updateStage(it)
+  }
+
+  /** Receive enroll progress event */
+  fun onUdfpsEvent(event: UdfpsEnrollEvent) {
+    when (event) {
+      is UdfpsProgress -> onEnrollmentProgress(event.remainingSteps, event.totalSteps)
+      is Acquired -> onAcquired(event.acquiredGood)
+      is UdfpsHelp -> onEnrollmentHelp()
+      is PointerDown -> onPointerDown()
+      is PointerUp -> onPointerUp()
+      OverlayShown -> overlayShown()
+      is UdfpsError -> udfpsError(event.errMsgId, event.errString)
+    }
+  }
+
+  /** Indicates if accessibility is enabled. */
+  fun setAccessibilityEnabled(enabled: Boolean) {
+    this.isAccessibilityEnabled = enabled
+    fingerprintProgressDrawable.setAccessibilityEnabled(enabled)
+  }
+
+  override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
+    invalidate()
+    super.onLayout(changed, left, top, right, bottom)
+    invalidate()
+  }
+
+  private fun udfpsError(errMsgId: Int, errString: String) {
+    Log.e(TAG, "Implement udfpsError")
+  }
+
+  private fun overlayShown() {
+    Log.e(TAG, "Implement overlayShown")
+  }
+
+  /** Receive enroll progress event */
+  private fun onEnrollmentProgress(remaining: Int, totalSteps: Int) {
+    post {
+      fingerprintIcon.onEnrollmentProgress(remaining, totalSteps)
+      fingerprintProgressDrawable.onEnrollmentProgress(remaining, totalSteps)
+    }
+  }
+
+  /** Receive enroll help event */
+  private fun onEnrollmentHelp() {
+    post { fingerprintProgressDrawable.onEnrollmentHelp(mRemainingSteps, mTotalSteps) }
+  }
+
+  /** Receive onAcquired event */
+  private fun onAcquired(isAcquiredGood: Boolean) {
+    val animateIfLastStepGood = isAcquiredGood && mRemainingSteps <= 2 && mRemainingSteps >= 0
+    post { if (animateIfLastStepGood) fingerprintProgressDrawable.onLastStepAcquired() }
+  }
+
+  /** Receive onPointerDown event */
+  private fun onPointerDown() {}
+
+  /** Receive onPointerUp event */
+  private fun onPointerUp() {}
+
+  companion object {
+    private const val TAG = "UdfpsEnrollView"
+  }
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsHearingAidsPresetsController.java b/src/com/android/settings/bluetooth/BluetoothDetailsHearingAidsPresetsController.java
index 43721f4..feecd90 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsHearingAidsPresetsController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsHearingAidsPresetsController.java
@@ -41,9 +41,12 @@
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.HapClientProfile;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.events.OnPause;
 import com.android.settingslib.core.lifecycle.events.OnResume;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
 import com.android.settingslib.utils.ThreadUtils;
 
 import java.util.List;
@@ -53,13 +56,16 @@
  */
 public class BluetoothDetailsHearingAidsPresetsController extends
         BluetoothDetailsController implements Preference.OnPreferenceChangeListener,
-        BluetoothHapClient.Callback, OnResume, OnPause {
+        BluetoothHapClient.Callback, LocalBluetoothProfileManager.ServiceListener,
+        OnStart, OnResume, OnPause, OnStop {
 
     private static final boolean DEBUG = true;
     private static final String TAG = "BluetoothDetailsHearingAidsPresetsController";
     static final String KEY_HEARING_AIDS_PRESETS = "hearing_aids_presets";
 
+    private final LocalBluetoothProfileManager mProfileManager;
     private final HapClientProfile mHapClientProfile;
+
     @Nullable
     private ListPreference mPreference;
 
@@ -69,26 +75,35 @@
             @NonNull CachedBluetoothDevice device,
             @NonNull Lifecycle lifecycle) {
         super(context, fragment, device, lifecycle);
-        mHapClientProfile = manager.getProfileManager().getHapClientProfile();
+        mProfileManager = manager.getProfileManager();
+        mHapClientProfile = mProfileManager.getHapClientProfile();
+    }
+
+    @Override
+    public void onStart() {
+        if (mHapClientProfile != null && !mHapClientProfile.isProfileReady()) {
+            mProfileManager.addServiceListener(this);
+        }
     }
 
     @Override
     public void onResume() {
+        registerHapCallback();
         super.onResume();
-        if (mHapClientProfile != null) {
-            mHapClientProfile.registerCallback(ThreadUtils.getBackgroundExecutor(), this);
-        }
     }
 
     @Override
     public void onPause() {
-        if (mHapClientProfile != null) {
-            mHapClientProfile.unregisterCallback(this);
-        }
+        unregisterHapCallback();
         super.onPause();
     }
 
     @Override
+    public void onStop() {
+        mProfileManager.removeServiceListener(this);
+    }
+
+    @Override
     public boolean onPreferenceChange(@NonNull Preference preference, @Nullable Object newValue) {
         if (TextUtils.equals(preference.getKey(), getPreferenceKey())) {
             if (newValue instanceof final String value
@@ -203,9 +218,8 @@
     public void onPresetSelectionFailed(@NonNull BluetoothDevice device, int reason) {
         if (device.equals(mCachedDevice.getDevice())) {
             if (DEBUG) {
-                Log.d(TAG,
-                        "onPresetSelectionFailed, device: " + device.getAddress()
-                                + ", reason: " + reason);
+                Log.d(TAG, "onPresetSelectionFailed, device: " + device.getAddress()
+                        + ", reason: " + reason);
             }
             mContext.getMainExecutor().execute(() -> {
                 refresh();
@@ -305,4 +319,41 @@
         Toast.makeText(mContext, R.string.bluetooth_hearing_aids_presets_error,
                 Toast.LENGTH_SHORT).show();
     }
+
+    private void registerHapCallback() {
+        if (mHapClientProfile != null) {
+            try {
+                mHapClientProfile.registerCallback(ThreadUtils.getBackgroundExecutor(), this);
+            } catch (IllegalArgumentException e) {
+                // The callback was already registered
+                Log.w(TAG, "Cannot register callback: " + e.getMessage());
+            }
+
+        }
+    }
+
+    private void unregisterHapCallback() {
+        if (mHapClientProfile != null) {
+            try {
+                mHapClientProfile.unregisterCallback(this);
+            } catch (IllegalArgumentException e) {
+                // The callback was never registered or was already unregistered
+                Log.w(TAG, "Cannot unregister callback: " + e.getMessage());
+            }
+        }
+    }
+
+    @Override
+    public void onServiceConnected() {
+        if (mHapClientProfile != null && mHapClientProfile.isProfileReady()) {
+            mProfileManager.removeServiceListener(this);
+            registerHapCallback();
+            refresh();
+        }
+    }
+
+    @Override
+    public void onServiceDisconnected() {
+        // Do nothing
+    }
 }
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingDialog.java b/src/com/android/settings/bluetooth/BluetoothPairingDialog.java
index d5b4211..347de4a 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingDialog.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingDialog.java
@@ -105,6 +105,8 @@
         registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_PAIRING_CANCEL));
         registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED));
         mReceiverRegistered = true;
+
+        closeSystemDialogs();
     }
 
     @Override
diff --git a/src/com/android/settings/core/SettingsBaseActivity.java b/src/com/android/settings/core/SettingsBaseActivity.java
index c282498..c9530ab 100644
--- a/src/com/android/settings/core/SettingsBaseActivity.java
+++ b/src/com/android/settings/core/SettingsBaseActivity.java
@@ -46,6 +46,7 @@
 import com.android.settings.core.CategoryMixin.CategoryHandler;
 import com.android.settingslib.core.lifecycle.HideNonSystemOverlayMixin;
 import com.android.settingslib.transition.SettingsTransitionHelper.TransitionType;
+import com.android.window.flags.Flags;
 
 import com.google.android.material.appbar.AppBarLayout;
 import com.google.android.material.appbar.CollapsingToolbarLayout;
@@ -92,8 +93,11 @@
             Log.w(TAG, "Devices lock task mode pinned.");
             finish();
         }
-        Utils.setupEdgeToEdge(this);
         final long startTime = System.currentTimeMillis();
+        if (Flags.enforceEdgeToEdge()) {
+            Utils.setupEdgeToEdge(this);
+            hideInternalActionBar();
+        }
         getLifecycle().addObserver(new HideNonSystemOverlayMixin(this));
         TextAppearanceConfig.setShouldLoadFontSynchronously(true);
 
@@ -291,4 +295,18 @@
         }
         return intent.getIntExtra(EXTRA_PAGE_TRANSITION_TYPE, TransitionType.TRANSITION_NONE);
     }
+
+    /**
+     * This internal ActionBar will be appeared automatically when the
+     * Utils.setupEdgeToEdge is invoked.
+     *
+     * @see Utils.setupEdgeToEdge
+     */
+    private void hideInternalActionBar() {
+        final View actionBarContainer =
+                findViewById(com.android.internal.R.id.action_bar_container);
+        if (actionBarContainer != null) {
+            actionBarContainer.setVisibility(View.GONE);
+        }
+    }
 }
diff --git a/src/com/android/settings/datausage/lib/NetworkStatsRepository.kt b/src/com/android/settings/datausage/lib/NetworkStatsRepository.kt
index 56b1931..484a8a3 100644
--- a/src/com/android/settings/datausage/lib/NetworkStatsRepository.kt
+++ b/src/com/android/settings/datausage/lib/NetworkStatsRepository.kt
@@ -93,13 +93,15 @@
             val buckets = mutableListOf<Bucket>()
             val bucket = NetworkStats.Bucket()
             while (getNextBucket(bucket)) {
-                buckets += Bucket(
-                    uid = bucket.uid,
-                    bytes = bucket.bytes,
-                    state = bucket.state,
-                    startTimeStamp = bucket.startTimeStamp,
-                    endTimeStamp = bucket.endTimeStamp,
-                )
+                if (bucket.bytes > 0) {
+                    buckets += Bucket(
+                        uid = bucket.uid,
+                        bytes = bucket.bytes,
+                        state = bucket.state,
+                        startTimeStamp = bucket.startTimeStamp,
+                        endTimeStamp = bucket.endTimeStamp,
+                    )
+                }
             }
             buckets
         }
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index d3bf8d8..bca2377 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -740,7 +740,6 @@
         controllers.add(new DefaultLaunchPreferenceController(context, "density"));
         controllers.add(new DefaultLaunchPreferenceController(context, "background_check"));
         controllers.add(new DefaultLaunchPreferenceController(context, "inactive_apps"));
-        controllers.add(new TarePreferenceController(context));
         controllers.add(new AutofillCategoryController(context, lifecycle));
         controllers.add(new AutofillLoggingLevelPreferenceController(context, lifecycle));
         controllers.add(new AutofillResetOptionsPreferenceController(context));
diff --git a/src/com/android/settings/development/TarePreferenceController.java b/src/com/android/settings/development/TarePreferenceController.java
deleted file mode 100644
index 8c70246..0000000
--- a/src/com/android/settings/development/TarePreferenceController.java
+++ /dev/null
@@ -1,70 +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.development;
-
-import android.app.tare.EconomyManager;
-import android.content.Context;
-import android.content.Intent;
-import android.os.UserManager;
-import android.provider.Settings;
-
-import androidx.preference.Preference;
-
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settings.development.tare.TareHomePage;
-import com.android.settingslib.development.DeveloperOptionsPreferenceController;
-
-/** PreferenceController that serves as an entry point to the TARE configuration screen. */
-public class TarePreferenceController extends
-        DeveloperOptionsPreferenceController implements PreferenceControllerMixin {
-
-    private static final String KEY_TARE = "tare";
-
-    private final EconomyManager mEconomyManager;
-    private final UserManager mUserManager;
-
-    public TarePreferenceController(Context context) {
-        super(context);
-        mEconomyManager = context.getSystemService(EconomyManager.class);
-        mUserManager = context.getSystemService(UserManager.class);
-    }
-
-    @Override
-    public boolean isAvailable() {
-        // Enable the UI if the dedicated flag enables it or if TARE itself is on.
-        final boolean settingEnabled = Settings.Global.getInt(
-                mContext.getContentResolver(), Settings.Global.SHOW_TARE_DEVELOPER_OPTIONS, 0) == 1;
-        final boolean isTareUiEnabled = settingEnabled
-                || mEconomyManager.getEnabledMode() != EconomyManager.ENABLED_MODE_OFF;
-        return isTareUiEnabled
-                && !mUserManager.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES);
-    }
-
-    @Override
-    public String getPreferenceKey() {
-        return KEY_TARE;
-    }
-
-    @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        if (!KEY_TARE.equals(preference.getKey())) {
-            return false;
-        }
-        mContext.startActivity(new Intent(mContext, TareHomePage.class));
-        return false;
-    }
-}
diff --git a/src/com/android/settings/development/tare/AlarmManagerFragment.java b/src/com/android/settings/development/tare/AlarmManagerFragment.java
deleted file mode 100644
index b55c7cf..0000000
--- a/src/com/android/settings/development/tare/AlarmManagerFragment.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2021 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.development.tare;
-
-import android.app.Fragment;
-import android.app.tare.EconomyManager;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ExpandableListView;
-import android.widget.ExpandableListView.OnChildClickListener;
-
-import androidx.annotation.Nullable;
-
-import com.android.settings.R;
-
-/**
- * Creates the AlarmManager fragment to display all the AlarmManager factors
- * when the AlarmManager policy is chosen in the dropdown TARE menu.
- */
-public class AlarmManagerFragment extends Fragment implements
-        TareFactorController.DataChangeListener {
-
-    private TareFactorController mFactorController;
-
-    private TareFactorExpandableListAdapter mExpandableListAdapter;
-
-    private String[] mGroups;
-    private String[][] mChildren;
-    private String[][] mKeys;
-
-    @Override
-    public void onCreate(@Nullable Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        mFactorController = TareFactorController.getInstance(getContext());
-        populateArrays();
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-            Bundle savedInstanceState) {
-        View v = inflater.inflate(R.layout.tare_policy_fragment, null);
-        ExpandableListView elv = (ExpandableListView) v.findViewById(R.id.factor_list);
-        mExpandableListAdapter = new TareFactorExpandableListAdapter(
-                mFactorController, LayoutInflater.from(getActivity()), mGroups, mChildren, mKeys);
-        elv.setGroupIndicator(null);
-        elv.setAdapter(mExpandableListAdapter);
-        elv.setOnChildClickListener(new OnChildClickListener() {
-            public boolean onChildClick(ExpandableListView parent, View v,
-                    int groupPosition, int childPosition, long id) {
-                final String key = mExpandableListAdapter.getKey(groupPosition, childPosition);
-                mFactorController.createDialog(key).show(getFragmentManager(), key);
-                return true;
-            }
-        });
-        return v;
-    }
-
-    @Override
-    public void onStart() {
-        super.onStart();
-        mFactorController.registerListener(this);
-    }
-
-    @Override
-    public void onStop() {
-        mFactorController.unregisterListener(this);
-        super.onStop();
-    }
-
-    @Override
-    public void onDataChanged() {
-        mExpandableListAdapter.notifyDataSetChanged();
-    }
-
-    private void populateArrays() {
-        final Resources resources = getResources();
-
-        mGroups = new String[]{
-                resources.getString(R.string.tare_consumption_limits),
-                resources.getString(R.string.tare_balances),
-                // resources.getString(R.string.tare_modifiers),
-                resources.getString(R.string.tare_actions_ctp),
-                resources.getString(R.string.tare_actions_base_price),
-                resources.getString(R.string.tare_rewards_instantaneous),
-                resources.getString(R.string.tare_rewards_ongoing),
-                resources.getString(R.string.tare_rewards_max)
-        };
-
-        mChildren = new String[][]{
-                resources.getStringArray(R.array.tare_consumption_limit_subfactors),
-                resources.getStringArray(R.array.tare_app_balance_subfactors),
-                // TODO: support
-                // resources.getStringArray(R.array.tare_modifiers_subfactors),
-                resources.getStringArray(R.array.tare_alarm_manager_actions),
-                resources.getStringArray(R.array.tare_alarm_manager_actions),
-                resources.getStringArray(R.array.tare_rewards_subfactors),
-                {resources.getString(R.string.tare_top_activity)},
-                resources.getStringArray(R.array.tare_rewards_subfactors)
-        };
-
-        mKeys = new String[][]{
-                {
-                        EconomyManager.KEY_AM_INITIAL_CONSUMPTION_LIMIT,
-                        EconomyManager.KEY_AM_MIN_CONSUMPTION_LIMIT,
-                        EconomyManager.KEY_AM_MAX_CONSUMPTION_LIMIT,
-                },
-                {
-                        EconomyManager.KEY_AM_MAX_SATIATED_BALANCE,
-                        EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_EXEMPTED,
-                        EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP,
-                        EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP
-                },
-                // {},
-                {
-                        EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP,
-                        EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP,
-                        EconomyManager.KEY_AM_ACTION_ALARM_EXACT_WAKEUP_CTP,
-                        EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP,
-                        EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP,
-                        EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP,
-                        EconomyManager.KEY_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP,
-                        EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_NONWAKEUP_CTP,
-                        EconomyManager.KEY_AM_ACTION_ALARM_ALARMCLOCK_CTP
-                },
-                {
-                        EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE,
-                        EconomyManager
-                                .KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE,
-                        EconomyManager.KEY_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE,
-                        EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_WAKEUP_BASE_PRICE,
-                        EconomyManager
-                                .KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_BASE_PRICE,
-                        EconomyManager
-                                .KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE,
-                        EconomyManager.KEY_AM_ACTION_ALARM_EXACT_NONWAKEUP_BASE_PRICE,
-                        EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_NONWAKEUP_BASE_PRICE,
-                        EconomyManager.KEY_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE
-                },
-                {
-                        EconomyManager.KEY_AM_REWARD_TOP_ACTIVITY_INSTANT,
-                        EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_INSTANT,
-                        EconomyManager.KEY_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT,
-                        EconomyManager.KEY_AM_REWARD_WIDGET_INTERACTION_INSTANT,
-                        EconomyManager.KEY_AM_REWARD_OTHER_USER_INTERACTION_INSTANT,
-                },
-                {EconomyManager.KEY_AM_REWARD_TOP_ACTIVITY_ONGOING},
-                {
-                        EconomyManager.KEY_AM_REWARD_TOP_ACTIVITY_MAX,
-                        EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_MAX,
-                        EconomyManager.KEY_AM_REWARD_NOTIFICATION_INTERACTION_MAX,
-                        EconomyManager.KEY_AM_REWARD_WIDGET_INTERACTION_MAX,
-                        EconomyManager.KEY_AM_REWARD_OTHER_USER_INTERACTION_MAX,
-                }
-        };
-    }
-}
diff --git a/src/com/android/settings/development/tare/DropdownActivity.java b/src/com/android/settings/development/tare/DropdownActivity.java
deleted file mode 100644
index 66b57dd..0000000
--- a/src/com/android/settings/development/tare/DropdownActivity.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2021 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.development.tare;
-
-import android.app.Activity;
-import android.app.Fragment;
-import android.app.FragmentTransaction;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Spinner;
-
-import com.android.settings.R;
-import com.android.settingslib.widget.SettingsSpinnerAdapter;
-
-/**
- * Dropdown activity to allow for the user to easily switch between the different TARE
- * policies in the developer options of settings. Depending on what is chosen, the fragment
- * containing that specific policies' factors will be generated.
- */
-public class DropdownActivity extends Activity {
-
-    private Fragment mAlarmManagerFragment;
-    private Fragment mJobSchedulerFragment;
-    private Spinner mSpinner;
-    static final String EXTRA_POLICY = "policy";
-    static final int POLICY_ALARM_MANAGER = 0;
-    static final int POLICY_JOB_SCHEDULER = 1;
-    private static final int DEFAULT_POLICY = POLICY_ALARM_MANAGER;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.tare_dropdown_page);
-
-        // Determines what policy fragment to open up to
-        Intent intent = getIntent();
-        int policy = intent.getIntExtra(EXTRA_POLICY, DEFAULT_POLICY);
-
-        mSpinner = findViewById(R.id.spinner);
-        mAlarmManagerFragment = new AlarmManagerFragment();
-        mJobSchedulerFragment = new JobSchedulerFragment();
-
-        String[] policies = getResources().getStringArray(R.array.tare_policies);
-
-        ArrayAdapter<String> arrayAdapter = new SettingsSpinnerAdapter<String>(this);
-        arrayAdapter.addAll(policies);
-        mSpinner.setAdapter(arrayAdapter);
-
-        mSpinner.setSelection(policy);
-        selectFragment(policy);
-
-        mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
-            @Override
-            public void onItemSelected(AdapterView<?> adapterView, View view, int position,
-                    long id) {
-                selectFragment(position);
-            }
-
-            @Override
-            public void onNothingSelected(AdapterView<?> adapterView) {
-            }
-        });
-    }
-
-    /** Selects the correct policy fragment to display based on user selection */
-    private void selectFragment(int policy) {
-        switch (policy) {
-            case POLICY_ALARM_MANAGER:
-                openFragment(mAlarmManagerFragment);
-                break;
-            case POLICY_JOB_SCHEDULER:
-                openFragment(mJobSchedulerFragment);
-                break;
-            default:
-                openFragment(mAlarmManagerFragment);
-        }
-    }
-
-    /** Opens the correct policy fragment */
-    private void openFragment(Fragment fragment) {
-        FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
-        fragmentTransaction.replace(R.id.frame_layout, fragment);
-        fragmentTransaction.commit();
-    }
-}
diff --git a/src/com/android/settings/development/tare/JobSchedulerFragment.java b/src/com/android/settings/development/tare/JobSchedulerFragment.java
deleted file mode 100644
index 7f5e663..0000000
--- a/src/com/android/settings/development/tare/JobSchedulerFragment.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2021 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.development.tare;
-
-import android.app.Fragment;
-import android.app.tare.EconomyManager;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ExpandableListView;
-import android.widget.ExpandableListView.OnChildClickListener;
-
-import androidx.annotation.Nullable;
-
-import com.android.settings.R;
-
-/**
- * Creates the JobScheduler fragment to display all the JobScheduler factors
- * when the JobScheduler policy is chosen in the dropdown TARE menu.
- */
-public class JobSchedulerFragment extends Fragment implements
-        TareFactorController.DataChangeListener {
-
-    private TareFactorController mFactorController;
-
-    private TareFactorExpandableListAdapter mExpandableListAdapter;
-
-    private String[] mGroups;
-    private String[][] mChildren;
-    private String[][] mKeys;
-
-    @Override
-    public void onCreate(@Nullable Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        mFactorController = TareFactorController.getInstance(getContext());
-        populateArrays();
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-            Bundle savedInstanceState) {
-        View v = inflater.inflate(R.layout.tare_policy_fragment, null);
-        ExpandableListView elv = (ExpandableListView) v.findViewById(R.id.factor_list);
-        mExpandableListAdapter = new TareFactorExpandableListAdapter(
-                mFactorController, LayoutInflater.from(getActivity()), mGroups, mChildren, mKeys);
-        elv.setGroupIndicator(null);
-        elv.setAdapter(mExpandableListAdapter);
-        elv.setOnChildClickListener(new OnChildClickListener() {
-            public boolean onChildClick(ExpandableListView parent, View v,
-                    int groupPosition, int childPosition, long id) {
-                final String key = mExpandableListAdapter.getKey(groupPosition, childPosition);
-                mFactorController.createDialog(key).show(getFragmentManager(), key);
-                return true;
-            }
-        });
-
-        return v;
-    }
-
-    @Override
-    public void onStart() {
-        super.onStart();
-        mFactorController.registerListener(this);
-    }
-
-    @Override
-    public void onStop() {
-        mFactorController.unregisterListener(this);
-        super.onStop();
-    }
-
-    @Override
-    public void onDataChanged() {
-        mExpandableListAdapter.notifyDataSetChanged();
-    }
-
-    private void populateArrays() {
-        final Resources resources = getResources();
-
-        mGroups = new String[]{
-                resources.getString(R.string.tare_consumption_limits),
-                resources.getString(R.string.tare_balances),
-                // mResources.getString(R.string.tare_modifiers),
-                resources.getString(R.string.tare_actions_ctp),
-                resources.getString(R.string.tare_actions_base_price),
-                resources.getString(R.string.tare_rewards_instantaneous),
-                resources.getString(R.string.tare_rewards_ongoing),
-                resources.getString(R.string.tare_rewards_max)
-        };
-
-        mChildren = new String[][]{
-                resources.getStringArray(R.array.tare_consumption_limit_subfactors),
-                resources.getStringArray(R.array.tare_job_scheduler_app_balance_subfactors),
-                // TODO: support
-                // mResources.getStringArray(R.array.tare_modifiers_subfactors),
-                resources.getStringArray(R.array.tare_job_scheduler_actions),
-                resources.getStringArray(R.array.tare_job_scheduler_actions),
-                resources.getStringArray(R.array.tare_job_scheduler_rewards_subfactors),
-                {resources.getString(R.string.tare_top_activity)},
-                resources.getStringArray(R.array.tare_job_scheduler_rewards_subfactors)
-        };
-
-        mKeys = new String[][]{
-                {
-                        EconomyManager.KEY_JS_INITIAL_CONSUMPTION_LIMIT,
-                        EconomyManager.KEY_JS_MIN_CONSUMPTION_LIMIT,
-                        EconomyManager.KEY_JS_MAX_CONSUMPTION_LIMIT,
-                },
-                {
-                        EconomyManager.KEY_JS_MAX_SATIATED_BALANCE,
-                        EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED,
-                        EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP,
-                        EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP,
-                        EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER,
-                },
-                // {},
-                {
-                        EconomyManager.KEY_JS_ACTION_JOB_MAX_START_CTP,
-                        EconomyManager.KEY_JS_ACTION_JOB_MAX_RUNNING_CTP,
-                        EconomyManager.KEY_JS_ACTION_JOB_HIGH_START_CTP,
-                        EconomyManager.KEY_JS_ACTION_JOB_HIGH_RUNNING_CTP,
-                        EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_START_CTP,
-                        EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_RUNNING_CTP,
-                        EconomyManager.KEY_JS_ACTION_JOB_LOW_START_CTP,
-                        EconomyManager.KEY_JS_ACTION_JOB_LOW_RUNNING_CTP,
-                        EconomyManager.KEY_JS_ACTION_JOB_MIN_START_CTP,
-                        EconomyManager.KEY_JS_ACTION_JOB_MIN_RUNNING_CTP,
-                        EconomyManager.KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP
-                },
-                {
-                        EconomyManager.KEY_JS_ACTION_JOB_MAX_START_BASE_PRICE,
-                        EconomyManager.KEY_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE,
-                        EconomyManager.KEY_JS_ACTION_JOB_HIGH_START_BASE_PRICE,
-                        EconomyManager.KEY_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE,
-                        EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE,
-                        EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE,
-                        EconomyManager.KEY_JS_ACTION_JOB_LOW_START_BASE_PRICE,
-                        EconomyManager.KEY_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE,
-                        EconomyManager.KEY_JS_ACTION_JOB_MIN_START_BASE_PRICE,
-                        EconomyManager.KEY_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE,
-                        EconomyManager.KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE
-                },
-                {
-                        EconomyManager.KEY_JS_REWARD_TOP_ACTIVITY_INSTANT,
-                        EconomyManager.KEY_JS_REWARD_NOTIFICATION_SEEN_INSTANT,
-                        EconomyManager.KEY_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT,
-                        EconomyManager.KEY_JS_REWARD_WIDGET_INTERACTION_INSTANT,
-                        EconomyManager.KEY_JS_REWARD_OTHER_USER_INTERACTION_INSTANT,
-                        EconomyManager.KEY_JS_REWARD_APP_INSTALL_INSTANT,
-                },
-                {EconomyManager.KEY_JS_REWARD_TOP_ACTIVITY_ONGOING},
-                {
-                        EconomyManager.KEY_JS_REWARD_TOP_ACTIVITY_MAX,
-                        EconomyManager.KEY_JS_REWARD_NOTIFICATION_SEEN_MAX,
-                        EconomyManager.KEY_JS_REWARD_NOTIFICATION_INTERACTION_MAX,
-                        EconomyManager.KEY_JS_REWARD_WIDGET_INTERACTION_MAX,
-                        EconomyManager.KEY_JS_REWARD_OTHER_USER_INTERACTION_MAX,
-                        EconomyManager.KEY_JS_REWARD_APP_INSTALL_MAX,
-                }
-        };
-    }
-}
diff --git a/src/com/android/settings/development/tare/OWNERS b/src/com/android/settings/development/tare/OWNERS
deleted file mode 100644
index 46d25c8..0000000
--- a/src/com/android/settings/development/tare/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 330055
-
-include platform/frameworks/base:/apex/jobscheduler/service/java/com/android/server/tare/OWNERS
\ No newline at end of file
diff --git a/src/com/android/settings/development/tare/TareFactorController.java b/src/com/android/settings/development/tare/TareFactorController.java
deleted file mode 100644
index 3407b7b..0000000
--- a/src/com/android/settings/development/tare/TareFactorController.java
+++ /dev/null
@@ -1,715 +0,0 @@
-/*
- * Copyright (C) 2021 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.development.tare;
-
-import static android.app.tare.EconomyManager.CAKE_IN_ARC;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE_CAKES;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE_CAKES;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP_CAKES;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE_CAKES;
-import static android.app.tare.EconomyManager.parseCreditValue;
-import static android.provider.Settings.Global.TARE_ALARM_MANAGER_CONSTANTS;
-import static android.provider.Settings.Global.TARE_JOB_SCHEDULER_CONSTANTS;
-
-import android.app.tare.EconomyManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.res.Resources;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Looper;
-import android.provider.Settings;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.KeyValueListParser;
-import android.util.Slog;
-
-import androidx.annotation.NonNull;
-
-import com.android.settings.R;
-
-/**
- * Takes an AlarmManager or JobScheduler csv string and parses it to get key:value pairs.
- * This allows us to populate a dialog with the correct information.
- */
-public class TareFactorController {
-    private static final String TAG = "TareFactorController";
-
-    private static TareFactorController sInstance;
-
-    private static final int POLICY_ALARM_MANAGER = 0;
-    private static final int POLICY_JOB_SCHEDULER = 1;
-
-    private final ContentResolver mContentResolver;
-    private final KeyValueListParser mParser = new KeyValueListParser(',');
-    private final Resources mResources;
-    private final ArrayMap<String, TareFactorData> mAlarmManagerMap = new ArrayMap<>();
-    private final ArrayMap<String, TareFactorData> mJobSchedulerMap = new ArrayMap<>();
-    private String mAlarmManagerConstants;
-    private String mJobSchedulerConstants;
-
-    private final ArraySet<DataChangeListener> mDataChangeListeners = new ArraySet<>();
-
-    private TareFactorController(Context context) {
-        mContentResolver = context.getContentResolver();
-        mResources = context.getResources();
-
-        ConfigObserver configObserver = new ConfigObserver(new Handler(Looper.getMainLooper()));
-        configObserver.start();
-
-        mAlarmManagerConstants =
-                Settings.Global.getString(mContentResolver, TARE_ALARM_MANAGER_CONSTANTS);
-        mJobSchedulerConstants =
-                Settings.Global.getString(mContentResolver, TARE_JOB_SCHEDULER_CONSTANTS);
-
-        initAlarmManagerMap();
-        parseAlarmManagerGlobalSettings();
-
-        initJobSchedulerMap();
-        parseJobSchedulerGlobalSettings();
-    }
-
-    static TareFactorController getInstance(Context context) {
-        synchronized (TareFactorController.class) {
-            if (sInstance == null) {
-                sInstance = new TareFactorController(context.getApplicationContext());
-            }
-        }
-        return sInstance;
-    }
-
-    /**
-     * Initialization for AlarmManager Map that sets a AM factor key to a title, default value, and
-     * policy type in a data object.
-     */
-    private void initAlarmManagerMap() {
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_EXEMPTED,
-                new TareFactorData(mResources.getString(R.string.tare_min_balance_exempted),
-                        EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP,
-                new TareFactorData(mResources.getString(R.string.tare_min_balance_headless_app),
-                        EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP,
-                new TareFactorData(mResources.getString(R.string.tare_min_balance_other_app),
-                        EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_MAX_SATIATED_BALANCE,
-                new TareFactorData(mResources.getString(R.string.tare_max_satiated_balance),
-                        EconomyManager.DEFAULT_AM_MAX_SATIATED_BALANCE_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_INITIAL_CONSUMPTION_LIMIT,
-                new TareFactorData(mResources.getString(R.string.tare_initial_consumption_limit),
-                        EconomyManager.DEFAULT_AM_INITIAL_CONSUMPTION_LIMIT_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_MIN_CONSUMPTION_LIMIT,
-                new TareFactorData(mResources.getString(R.string.tare_min_consumption_limit),
-                        EconomyManager.DEFAULT_AM_MIN_CONSUMPTION_LIMIT_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_MAX_CONSUMPTION_LIMIT,
-                new TareFactorData(mResources.getString(R.string.tare_max_consumption_limit),
-                        EconomyManager.DEFAULT_AM_MAX_CONSUMPTION_LIMIT_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_TOP_ACTIVITY_INSTANT,
-                new TareFactorData(mResources.getString(R.string.tare_top_activity),
-                        EconomyManager.DEFAULT_AM_REWARD_TOP_ACTIVITY_INSTANT_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_TOP_ACTIVITY_ONGOING,
-                new TareFactorData(mResources.getString(R.string.tare_top_activity),
-                        EconomyManager.DEFAULT_AM_REWARD_TOP_ACTIVITY_ONGOING_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_TOP_ACTIVITY_MAX,
-                new TareFactorData(mResources.getString(R.string.tare_top_activity),
-                        EconomyManager.DEFAULT_AM_REWARD_TOP_ACTIVITY_MAX_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_INSTANT,
-                new TareFactorData(mResources.getString(R.string.tare_notification_seen),
-                        EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_INSTANT_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_ONGOING,
-                new TareFactorData(mResources.getString(R.string.tare_notification_seen),
-                        EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_ONGOING_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_MAX,
-                new TareFactorData(mResources.getString(R.string.tare_notification_seen),
-                        EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_MAX_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_INSTANT,
-                new TareFactorData(mResources.getString(R.string.tare_notification_seen_15_min),
-                        EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_INSTANT_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_ONGOING,
-                new TareFactorData(mResources.getString(R.string.tare_notification_seen_15_min),
-                        EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_ONGOING_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_MAX,
-                new TareFactorData(mResources.getString(R.string.tare_notification_seen_15_min),
-                        EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_MAX_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT,
-                new TareFactorData(mResources.getString(R.string.tare_notification_interaction),
-                        EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_INTERACTION_ONGOING,
-                new TareFactorData(mResources.getString(R.string.tare_notification_interaction),
-                        EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_ONGOING_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_INTERACTION_MAX,
-                new TareFactorData(mResources.getString(R.string.tare_notification_interaction),
-                        EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_MAX_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_WIDGET_INTERACTION_INSTANT,
-                new TareFactorData(mResources.getString(R.string.tare_widget_interaction),
-                        EconomyManager.DEFAULT_AM_REWARD_WIDGET_INTERACTION_INSTANT_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_WIDGET_INTERACTION_ONGOING,
-                new TareFactorData(mResources.getString(R.string.tare_widget_interaction),
-                        EconomyManager.DEFAULT_AM_REWARD_WIDGET_INTERACTION_ONGOING_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_WIDGET_INTERACTION_MAX,
-                new TareFactorData(mResources.getString(R.string.tare_widget_interaction),
-                        EconomyManager.DEFAULT_AM_REWARD_WIDGET_INTERACTION_MAX_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_OTHER_USER_INTERACTION_INSTANT,
-                new TareFactorData(mResources.getString(R.string.tare_other_interaction),
-                        EconomyManager.DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_INSTANT_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_OTHER_USER_INTERACTION_ONGOING,
-                new TareFactorData(mResources.getString(R.string.tare_other_interaction),
-                        EconomyManager.DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_ONGOING_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_OTHER_USER_INTERACTION_MAX,
-                new TareFactorData(mResources.getString(R.string.tare_other_interaction),
-                        EconomyManager.DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_MAX_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_wakeup_exact_idle),
-                        EconomyManager
-                                .DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_wakeup_inexact_idle),
-                        EconomyManager
-                                .DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_EXACT_WAKEUP_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_wakeup_exact),
-                        EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_CTP_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_wakeup_inexact),
-                        EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(
-                EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_nonwakeup_exact_idle),
-                        EconomyManager
-                                .DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_nonwakeup_exact),
-                        EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(
-                EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_nonwakeup_inexact_idle),
-                        DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_NONWAKEUP_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_nonwakeup_inexact),
-                        EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_CTP_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_ALARMCLOCK_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
-                        EconomyManager.DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_CTP_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(
-                EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
-                        DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(
-                EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
-                        DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
-                        EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_WAKEUP_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
-                        EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(
-                EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
-                        EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_EXACT_NONWAKEUP_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
-                        EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(
-                EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
-                        DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_NONWAKEUP_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
-                        EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_BASE_PRICE_CAKES,
-                        POLICY_ALARM_MANAGER));
-        mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
-                        EconomyManager.DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE_CAKES,
-                        POLICY_ALARM_MANAGER));
-    }
-
-    /**
-     * Initialization for JobScheduler Map that sets a JS factor key to a title, default value, and
-     * policy type in a data object.
-     */
-    private void initJobSchedulerMap() {
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED,
-                new TareFactorData(mResources.getString(R.string.tare_min_balance_exempted),
-                        EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP,
-                new TareFactorData(mResources.getString(R.string.tare_min_balance_headless_app),
-                        EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP,
-                new TareFactorData(mResources.getString(R.string.tare_min_balance_other_app),
-                        EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER,
-                new TareFactorData(
-                        mResources.getString(R.string.tare_min_balance_addition_app_updater),
-                        EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_INCREMENT_APP_UPDATER_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_MAX_SATIATED_BALANCE,
-                new TareFactorData(mResources.getString(R.string.tare_max_satiated_balance),
-                        EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_INITIAL_CONSUMPTION_LIMIT,
-                new TareFactorData(mResources.getString(R.string.tare_initial_consumption_limit),
-                        EconomyManager.DEFAULT_JS_INITIAL_CONSUMPTION_LIMIT_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_MIN_CONSUMPTION_LIMIT,
-                new TareFactorData(mResources.getString(R.string.tare_min_consumption_limit),
-                        EconomyManager.DEFAULT_JS_MIN_CONSUMPTION_LIMIT_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_MAX_CONSUMPTION_LIMIT,
-                new TareFactorData(mResources.getString(R.string.tare_max_consumption_limit),
-                        EconomyManager.DEFAULT_JS_MAX_CONSUMPTION_LIMIT_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_APP_INSTALL_INSTANT,
-                new TareFactorData(mResources.getString(R.string.tare_app_install),
-                        EconomyManager.DEFAULT_JS_REWARD_APP_INSTALL_INSTANT_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_APP_INSTALL_ONGOING,
-                new TareFactorData(mResources.getString(R.string.tare_app_install),
-                        EconomyManager.DEFAULT_JS_REWARD_APP_INSTALL_ONGOING_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_APP_INSTALL_MAX,
-                new TareFactorData(mResources.getString(R.string.tare_app_install),
-                        EconomyManager.DEFAULT_JS_REWARD_APP_INSTALL_MAX_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_TOP_ACTIVITY_INSTANT,
-                new TareFactorData(mResources.getString(R.string.tare_top_activity),
-                        EconomyManager.DEFAULT_JS_REWARD_TOP_ACTIVITY_INSTANT_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_TOP_ACTIVITY_ONGOING,
-                new TareFactorData(mResources.getString(R.string.tare_top_activity),
-                        EconomyManager.DEFAULT_JS_REWARD_TOP_ACTIVITY_ONGOING_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_TOP_ACTIVITY_MAX,
-                new TareFactorData(mResources.getString(R.string.tare_top_activity),
-                        EconomyManager.DEFAULT_JS_REWARD_TOP_ACTIVITY_MAX_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_NOTIFICATION_SEEN_INSTANT,
-                new TareFactorData(mResources.getString(R.string.tare_notification_seen),
-                        EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_SEEN_INSTANT_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_NOTIFICATION_SEEN_ONGOING,
-                new TareFactorData(mResources.getString(R.string.tare_notification_seen),
-                        EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_SEEN_ONGOING_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_NOTIFICATION_SEEN_MAX,
-                new TareFactorData(mResources.getString(R.string.tare_notification_seen),
-                        EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_SEEN_MAX_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT,
-                new TareFactorData(mResources.getString(R.string.tare_notification_interaction),
-                        EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_NOTIFICATION_INTERACTION_ONGOING,
-                new TareFactorData(mResources.getString(R.string.tare_notification_interaction),
-                        EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_ONGOING_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_NOTIFICATION_INTERACTION_MAX,
-                new TareFactorData(mResources.getString(R.string.tare_notification_interaction),
-                        EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_MAX_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_WIDGET_INTERACTION_INSTANT,
-                new TareFactorData(mResources.getString(R.string.tare_widget_interaction),
-                        EconomyManager.DEFAULT_JS_REWARD_WIDGET_INTERACTION_INSTANT_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_WIDGET_INTERACTION_ONGOING,
-                new TareFactorData(mResources.getString(R.string.tare_widget_interaction),
-                        EconomyManager.DEFAULT_JS_REWARD_WIDGET_INTERACTION_ONGOING_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_WIDGET_INTERACTION_MAX,
-                new TareFactorData(mResources.getString(R.string.tare_widget_interaction),
-                        EconomyManager.DEFAULT_JS_REWARD_WIDGET_INTERACTION_MAX_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_OTHER_USER_INTERACTION_INSTANT,
-                new TareFactorData(mResources.getString(R.string.tare_other_interaction),
-                        EconomyManager.DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_INSTANT_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_OTHER_USER_INTERACTION_ONGOING,
-                new TareFactorData(mResources.getString(R.string.tare_other_interaction),
-                        EconomyManager.DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_ONGOING_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_OTHER_USER_INTERACTION_MAX,
-                new TareFactorData(mResources.getString(R.string.tare_other_interaction),
-                        EconomyManager.DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_MAX_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MAX_START_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_job_max_start),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_START_CTP_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MAX_RUNNING_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_job_max_running),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_RUNNING_CTP_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_HIGH_START_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_job_high_start),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_START_CTP_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_HIGH_RUNNING_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_job_high_running),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_CTP_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_START_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_job_default_start),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_START_CTP_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_RUNNING_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_job_default_running),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_CTP_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_LOW_START_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_job_low_start),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_START_CTP_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(
-                EconomyManager.KEY_JS_ACTION_JOB_LOW_RUNNING_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_job_low_running),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_RUNNING_CTP_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MIN_START_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_job_min_start),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_START_CTP_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(
-                EconomyManager.KEY_JS_ACTION_JOB_MIN_RUNNING_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_job_min_running),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_RUNNING_CTP_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP,
-                new TareFactorData(mResources.getString(R.string.tare_job_timeout_penalty),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MAX_START_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_job_max_start),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_START_BASE_PRICE_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(
-                EconomyManager.KEY_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_job_max_running),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(
-                EconomyManager.KEY_JS_ACTION_JOB_HIGH_START_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_job_high_start),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_START_BASE_PRICE_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_job_high_running),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_job_default_start),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(
-                EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_job_default_running),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_LOW_START_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_job_low_start),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_START_BASE_PRICE_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(
-                EconomyManager.KEY_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_job_low_running),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MIN_START_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_job_min_start),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_START_BASE_PRICE_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_job_min_running),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE_CAKES,
-                        POLICY_JOB_SCHEDULER));
-        mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE,
-                new TareFactorData(mResources.getString(R.string.tare_job_timeout_penalty),
-                        EconomyManager.DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE_CAKES,
-                        POLICY_JOB_SCHEDULER));
-    }
-
-    /**
-     * Parses the AM constant from Settings.Global to get to the current value.
-     */
-    private void parseAlarmManagerGlobalSettings() {
-        parseSettingsIntoMap(mAlarmManagerConstants, mAlarmManagerMap);
-    }
-
-    /**
-     * Parses the JS constant from Settings.Global to get to the current value.
-     */
-    private void parseJobSchedulerGlobalSettings() {
-        parseSettingsIntoMap(mJobSchedulerConstants, mJobSchedulerMap);
-    }
-
-    private void parseSettingsIntoMap(String constants, ArrayMap<String, TareFactorData> map) {
-        try {
-            mParser.setString(constants);
-        } catch (Exception e) {
-            Slog.e(TAG, "Bad string constants value", e);
-        }
-
-        for (int i = map.size() - 1; i >= 0; --i) {
-            final String key = map.keyAt(i);
-            final TareFactorData data = map.valueAt(i);
-            data.currentValue = parseCreditValue(mParser.getString(key, null), data.defaultValue);
-        }
-    }
-
-    @NonNull
-    private ArrayMap<String, TareFactorData> getMap(int factorPolicy) {
-        switch (factorPolicy) {
-            case POLICY_ALARM_MANAGER:
-                return mAlarmManagerMap;
-            case POLICY_JOB_SCHEDULER:
-                return mJobSchedulerMap;
-            default:
-                throw new IllegalArgumentException("Invalid factor policy given");
-        }
-    }
-
-    /**
-     * Takes a key and factor policy as input and grabs the title linked to it.
-     *
-     * @param key          the key of the factor you want to get the title of
-     * @param factorPolicy the policy you want the title of
-     */
-    private String getTitle(String key, int factorPolicy) {
-        final ArrayMap<String, TareFactorData> currentMap = getMap(factorPolicy);
-        return currentMap.get(key).title;
-    }
-
-    /**
-     * Takes a key and factor policy as input and grabs the current value linked to it.
-     *
-     * @param key          the key of the factor you want to get the default value of
-     * @param factorPolicy the policy you want the current value of
-     */
-    private long getCurrentValue(String key, int factorPolicy) {
-        final ArrayMap<String, TareFactorData> currentMap = getMap(factorPolicy);
-        return currentMap.get(key).currentValue;
-    }
-
-    /**
-     * Takes a key as input and grabs the factor type linked to it.
-     *
-     * @param key the key of the factor you want to get the factor type of
-     */
-    private int getFactorType(String key) {
-        ArrayMap<String, TareFactorData> currentMap;
-        if (mAlarmManagerMap.containsKey(key)) {
-            currentMap = mAlarmManagerMap;
-        } else if (mJobSchedulerMap.containsKey(key)) {
-            currentMap = mJobSchedulerMap;
-        } else {
-            throw new IllegalArgumentException("Couldn't link key '" + key + "' to a policy");
-        }
-        return currentMap.get(key).factorPolicy;
-    }
-
-    long getValue(String key) {
-        final int policy = getFactorType(key);
-        return getCurrentValue(key, policy);
-    }
-
-    /**
-     * Takes a key,edited value, and factor policy as input and assigns the new edited value to
-     * be the new current value for that factors key.
-     *
-     * @param key          the key of the factor you want to get the default value of
-     * @param editedValue  the value entered by the user in the dialog
-     * @param factorPolicy policy being updated
-     */
-    public void updateValue(String key, long editedValue, int factorPolicy) {
-        final ArrayMap<String, TareFactorData> map = getMap(factorPolicy);
-
-        final TareFactorData data = map.get(key);
-        if (data.currentValue == editedValue) {
-            return;
-        }
-        data.currentValue = editedValue;
-        rebuildPolicyConstants(factorPolicy);
-    }
-
-    /**
-     * Iterates through the factor policy map for keys and current values to
-     * rebuild a current string that is then assigned to be the new global settings string.
-     *
-     * @param factorPolicy policy being updated
-     */
-    private void rebuildPolicyConstants(int factorPolicy) {
-        switch (factorPolicy) {
-            case POLICY_ALARM_MANAGER:
-                writeConstantsToSettings(mAlarmManagerMap, TARE_ALARM_MANAGER_CONSTANTS);
-                break;
-            case POLICY_JOB_SCHEDULER:
-                writeConstantsToSettings(mJobSchedulerMap, TARE_JOB_SCHEDULER_CONSTANTS);
-                break;
-        }
-    }
-
-    private void writeConstantsToSettings(ArrayMap<String, TareFactorData> factorMap,
-            String settingsKey) {
-        final StringBuilder constantsStringBuilder = new StringBuilder();
-
-        for (int i = 0, size = factorMap.size(); i < size; ++i) {
-            final TareFactorData factor = factorMap.valueAt(i);
-            if (factor.currentValue == factor.defaultValue) {
-                continue;
-            }
-
-            if (constantsStringBuilder.length() > 0) {
-                constantsStringBuilder.append(",");
-            }
-
-            constantsStringBuilder
-                    .append(factorMap.keyAt(i))
-                    .append("=");
-            if (factor.currentValue % CAKE_IN_ARC == 0) {
-                constantsStringBuilder
-                        .append(factor.currentValue / CAKE_IN_ARC)
-                        .append("A");
-            } else {
-                constantsStringBuilder
-                        .append(factor.currentValue)
-                        .append("ck");
-            }
-        }
-
-        Settings.Global.putString(mContentResolver, settingsKey, constantsStringBuilder.toString());
-    }
-
-    /**
-     * Creates a dialog with the values linked to the key.
-     *
-     * @param key the key of the factor you want to get the default value of
-     */
-    public TareFactorDialogFragment createDialog(String key) {
-        int policy = getFactorType(key);
-        return new TareFactorDialogFragment(getTitle(key, policy), key,
-                getCurrentValue(key, policy), policy, this);
-    }
-
-    /**
-     * Data object that holds a title,default value,and current value for a key.
-     */
-    private static class TareFactorData {
-        public final String title;
-        public final long defaultValue;
-        public final int factorPolicy;
-        public long currentValue;
-
-        TareFactorData(String title, long defaultValue, int factorPolicy) {
-            this.title = title;
-            this.defaultValue = defaultValue;
-            this.factorPolicy = factorPolicy;
-            this.currentValue = defaultValue;
-        }
-    }
-
-    interface DataChangeListener {
-        void onDataChanged();
-    }
-
-    void registerListener(DataChangeListener listener) {
-        mDataChangeListeners.add(listener);
-    }
-
-    void unregisterListener(DataChangeListener listener) {
-        mDataChangeListeners.remove(listener);
-    }
-
-    void notifyListeners() {
-        for (int i = mDataChangeListeners.size() - 1; i >= 0; --i) {
-            mDataChangeListeners.valueAt(i).onDataChanged();
-        }
-    }
-
-    private class ConfigObserver extends ContentObserver {
-
-        ConfigObserver(Handler handler) {
-            super(handler);
-        }
-
-        public void start() {
-            mContentResolver.registerContentObserver(
-                    Settings.Global.getUriFor(TARE_ALARM_MANAGER_CONSTANTS), false, this);
-            mContentResolver.registerContentObserver(
-                    Settings.Global.getUriFor(TARE_JOB_SCHEDULER_CONSTANTS), false, this);
-        }
-
-        @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            if (uri.equals(Settings.Global.getUriFor(TARE_ALARM_MANAGER_CONSTANTS))) {
-                mAlarmManagerConstants =
-                        Settings.Global.getString(mContentResolver, TARE_ALARM_MANAGER_CONSTANTS);
-                parseAlarmManagerGlobalSettings();
-                notifyListeners();
-            } else if (uri.equals(Settings.Global.getUriFor(TARE_JOB_SCHEDULER_CONSTANTS))) {
-                mJobSchedulerConstants =
-                        Settings.Global.getString(mContentResolver, TARE_JOB_SCHEDULER_CONSTANTS);
-                parseJobSchedulerGlobalSettings();
-                notifyListeners();
-            }
-        }
-    }
-}
diff --git a/src/com/android/settings/development/tare/TareFactorDialogFragment.java b/src/com/android/settings/development/tare/TareFactorDialogFragment.java
deleted file mode 100644
index 269e209..0000000
--- a/src/com/android/settings/development/tare/TareFactorDialogFragment.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2021 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.development.tare;
-
-import static android.app.tare.EconomyManager.CAKE_IN_ARC;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.content.Context;
-import android.os.Bundle;
-import android.text.InputType;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.EditText;
-import android.widget.Spinner;
-
-import androidx.annotation.NonNull;
-
-import com.android.settings.R;
-import com.android.settings.Utils;
-
-/**
- * Dialog Fragment for changing tare factor values
- */
-public class TareFactorDialogFragment extends DialogFragment {
-    private static final String TAG = "TareDialogFragment";
-
-    // This follows the order in strings.xml:tare_units array.
-    private static final int UNIT_IDX_ARC = 0;
-    private static final int UNIT_IDX_CAKE = 1;
-
-    private final String mFactorKey;
-    private final String mFactorTitle;
-    private final long mFactorValue;
-    private final int mFactorPolicy;
-    private final TareFactorController mTareFactorController;
-
-    private EditText mFactorValueView;
-    private Spinner mUnitSpinner;
-
-    /**
-     * @param title        the title that will show at the top of the Dialog for the Factor
-     * @param key          the key of the Factor being initialized.
-     * @param currentValue the current value set for the Factor
-     */
-    public TareFactorDialogFragment(@NonNull String title, @NonNull String key, long currentValue,
-            int factorPolicy, TareFactorController tareFactorController) {
-        mFactorTitle = title;
-        mFactorKey = key;
-        mFactorValue = currentValue;
-        mFactorPolicy = factorPolicy;
-        mTareFactorController = tareFactorController;
-    }
-
-    @NonNull
-    @Override
-    public Dialog onCreateDialog(Bundle savedInstanceState) {
-        AlertDialog.Builder builder = new AlertDialog.Builder(
-                getActivity())
-                .setTitle(mFactorTitle)
-                .setView(createDialogView())
-                .setPositiveButton(R.string.tare_dialog_confirm_button_title, (dialog, which) -> {
-
-                    final String stringValue = mFactorValueView.getText().toString();
-                    long newVal = mFactorValue;
-                    try {
-                        newVal = Long.parseLong(stringValue);
-                        if (mUnitSpinner.getSelectedItemPosition() == UNIT_IDX_ARC) {
-                            // Convert ARC to cake
-                            newVal *= CAKE_IN_ARC;
-                        }
-                    } catch (NumberFormatException e) {
-                        Log.e(TAG, "Error parsing '" + stringValue + "'. Using "
-                                + mFactorValue + " instead", e);
-                    }
-                    mTareFactorController.updateValue(mFactorKey, newVal, mFactorPolicy);
-                })
-                .setNegativeButton(android.R.string.cancel, (dialog, which) -> {
-                    // When the negative button is clicked do nothing
-                });
-
-        return builder.create();
-    }
-
-    /**
-     * Creates a view for the factor Dialog that currently
-     * is linked to the basic dialog_edittext.xml layout.
-     */
-    private View createDialogView() {
-        final LayoutInflater layoutInflater = (LayoutInflater) getActivity()
-                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        View layout = layoutInflater.inflate(R.layout.dialog_edittext_dropdown, null);
-        mFactorValueView = layout.findViewById(R.id.edittext);
-        mFactorValueView.setInputType(InputType.TYPE_CLASS_NUMBER);
-
-        mUnitSpinner = layout.findViewById(R.id.spinner);
-        final String[] units = getResources().getStringArray(R.array.tare_units);
-        ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(
-                getActivity(), android.R.layout.simple_spinner_item, units);
-        mUnitSpinner.setAdapter(spinnerArrayAdapter);
-
-        final int unitIdx;
-        if (mFactorValue % CAKE_IN_ARC == 0) {
-            mFactorValueView.setText(String.format("%d", mFactorValue / CAKE_IN_ARC));
-            unitIdx = UNIT_IDX_ARC;
-        } else {
-            mFactorValueView.setText(String.format("%d", mFactorValue));
-            unitIdx = UNIT_IDX_CAKE;
-        }
-        mUnitSpinner.setSelection(unitIdx);
-        mUnitSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
-            private int mSelectedPosition = unitIdx;
-
-            @Override
-            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-                if (mSelectedPosition == position) {
-                    return;
-                }
-                mSelectedPosition = position;
-                final String stringValue = mFactorValueView.getText().toString();
-
-                try {
-                    long newVal = Long.parseLong(stringValue);
-                    if (mUnitSpinner.getSelectedItemPosition() == UNIT_IDX_ARC) {
-                        // Convert cake to ARC
-                        newVal /= CAKE_IN_ARC;
-                    } else {
-                        // Convert ARC to cake
-                        newVal *= CAKE_IN_ARC;
-                    }
-                    mFactorValueView.setText(String.format("%d", newVal));
-                } catch (NumberFormatException e) {
-                    Log.e(TAG, "Error parsing '" + stringValue + "'", e);
-                }
-            }
-
-            @Override
-            public void onNothingSelected(AdapterView<?> parent) {
-
-            }
-        });
-
-        Utils.setEditTextCursorPosition(mFactorValueView);
-        return layout;
-    }
-}
diff --git a/src/com/android/settings/development/tare/TareFactorExpandableListAdapter.java b/src/com/android/settings/development/tare/TareFactorExpandableListAdapter.java
deleted file mode 100644
index 9c78d06..0000000
--- a/src/com/android/settings/development/tare/TareFactorExpandableListAdapter.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.development.tare;
-
-import static android.app.tare.EconomyManager.CAKE_IN_ARC;
-
-import android.annotation.SuppressLint;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseExpandableListAdapter;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-
-import com.android.settings.R;
-
-/**
- * Creates the expandable list that will allow modifying individual factors.
- */
-public class TareFactorExpandableListAdapter extends BaseExpandableListAdapter {
-
-    private final LayoutInflater mLayoutInflater;
-    private final TareFactorController mFactorController;
-
-    private final String[] mGroups;
-    private final String[][] mChildren;
-    private final String[][] mKeys;
-
-    TareFactorExpandableListAdapter(TareFactorController factorController,
-            LayoutInflater layoutInflater, String[] groups, String[][] children, String[][] keys) {
-        mLayoutInflater = layoutInflater;
-        mFactorController = factorController;
-
-        mGroups = groups;
-        mChildren = children;
-        mKeys = keys;
-
-        validateMappings();
-    }
-
-    private void validateMappings() {
-        if (mGroups.length != mChildren.length) {
-            throw new IllegalStateException("groups and children don't have the same length");
-        }
-        if (mChildren.length != mKeys.length) {
-            throw new IllegalStateException("children and keys don't have the same length");
-        }
-        for (int i = 0; i < mChildren.length; ++i) {
-            if (mChildren[i].length != mKeys[i].length) {
-                throw new IllegalStateException(
-                        "children and keys don't have the same length in row " + i);
-            }
-        }
-    }
-
-    @Override
-    public int getGroupCount() {
-        return mGroups.length;
-    }
-
-    @Override
-    public int getChildrenCount(int groupPosition) {
-        return mChildren[groupPosition].length;
-    }
-
-    @Override
-    public Object getGroup(int groupPosition) {
-        return mGroups[groupPosition];
-    }
-
-    @Override
-    public Object getChild(int groupPosition, int childPosition) {
-        return mChildren[groupPosition][childPosition];
-    }
-
-    @Override
-    public long getGroupId(int groupPosition) {
-        return groupPosition;
-    }
-
-    @Override
-    public long getChildId(int groupPosition, int childPosition) {
-        return childPosition;
-    }
-
-    @NonNull
-    String getKey(int groupPosition, int childPosition) {
-        return mKeys[groupPosition][childPosition];
-    }
-
-    @Override
-    public boolean hasStableIds() {
-        return true;
-    }
-
-    @Override
-    public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
-            ViewGroup parent) {
-        if (convertView == null) {
-            convertView = mLayoutInflater.inflate(android.R.layout.simple_list_item_1, parent,
-                    false);
-        }
-        TextView factor = convertView.findViewById(android.R.id.text1);
-        factor.setText(getGroup(groupPosition).toString());
-        return convertView;
-    }
-
-    @Override
-    @SuppressLint("InflateParams") // AdapterView doesn't support addView
-    public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
-            View convertView, ViewGroup parent) {
-        // Here a custom child item is used instead of android.R.simple_list_item_2 because it
-        // is more customizable for this specific UI
-        if (convertView == null) {
-            convertView = mLayoutInflater.inflate(R.layout.tare_child_item, null);
-        }
-        TextView factor = convertView.findViewById(R.id.factor);
-        TextView value = convertView.findViewById(R.id.factor_number);
-
-        factor.setText(getChild(groupPosition, childPosition).toString());
-        value.setText(cakeToString(
-                mFactorController.getValue(getKey(groupPosition, childPosition))));
-
-        return convertView;
-    }
-
-    @NonNull
-    private static String cakeToString(long cakes) {
-        // Resources.getQuantityString doesn't handle floating point numbers, so doing this manually
-        if (cakes == 0) {
-            return "0";
-        }
-        final long sub = cakes % CAKE_IN_ARC;
-        final long arcs = (int) (cakes / CAKE_IN_ARC);
-        if (arcs == 0) {
-            return sub + " c";
-        }
-        StringBuilder sb = new StringBuilder();
-        sb.append(arcs);
-        if (sub > 0) {
-            sb.append(".").append(String.format("%03d", sub / (CAKE_IN_ARC / 1000)));
-        }
-        sb.append(" A");
-        return sb.toString();
-    }
-
-    @Override
-    public boolean isChildSelectable(int groupPosition, int childPosition) {
-        return true;
-    }
-}
diff --git a/src/com/android/settings/development/tare/TareHomePage.java b/src/com/android/settings/development/tare/TareHomePage.java
deleted file mode 100644
index 0eb93fc..0000000
--- a/src/com/android/settings/development/tare/TareHomePage.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2021 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.development.tare;
-
-import static com.android.settings.development.tare.DropdownActivity.EXTRA_POLICY;
-import static com.android.settings.development.tare.DropdownActivity.POLICY_ALARM_MANAGER;
-import static com.android.settings.development.tare.DropdownActivity.POLICY_JOB_SCHEDULER;
-
-import android.app.Activity;
-import android.app.tare.EconomyManager;
-import android.content.Intent;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.provider.DeviceConfig;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.View;
-import android.widget.Button;
-import android.widget.CompoundButton;
-import android.widget.CompoundButton.OnCheckedChangeListener;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import com.android.settings.R;
-
-/** Class for creating the TARE homepage in settings */
-public class TareHomePage extends Activity {
-    private static final String TAG = "TareHomePage";
-
-    private CompoundButton mOnSwitch;
-    private Button mRevButton;
-    private TextView mAlarmManagerView;
-    private TextView mJobSchedulerView;
-    private ConfigObserver mConfigObserver;
-
-    private static final int SETTING_VALUE_DEFAULT = -1;
-    private static final int SETTING_VALUE_OFF = 0;
-    private static final int SETTING_VALUE_ON = 1;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.tare_homepage);
-
-        mOnSwitch = findViewById(R.id.on_switch);
-        mRevButton = findViewById(R.id.revert_button);
-        mAlarmManagerView = findViewById(R.id.alarmmanager);
-        mJobSchedulerView = findViewById(R.id.jobscheduler);
-
-        mConfigObserver = new ConfigObserver(new Handler(Looper.getMainLooper()));
-
-        mOnSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
-            @Override
-            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-                if (mConfigObserver.mEnableTareSetting == SETTING_VALUE_DEFAULT
-                        && isChecked == mConfigObserver.getDefaultEnabledStatus()) {
-                    // Don't bother writing something that's not new information. It would make
-                    // it hard to use DeviceConfig if we did.
-                    return;
-                }
-                Settings.Global.putInt(getContentResolver(),
-                        Settings.Global.ENABLE_TARE,
-                        isChecked ? SETTING_VALUE_ON : SETTING_VALUE_OFF);
-            }
-        });
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        mConfigObserver.start();
-    }
-
-    @Override
-    protected void onPause() {
-        mConfigObserver.stop();
-        super.onPause();
-    }
-
-    /** Reverts the TARE settings to the original default settings */
-    public void revertSettings(View v) {
-        Toast.makeText(this, R.string.tare_settings_reverted_toast, Toast.LENGTH_LONG).show();
-        final boolean wasSettingsDefault =
-                mConfigObserver.mEnableTareSetting == SETTING_VALUE_DEFAULT;
-        Settings.Global.putString(getApplicationContext().getContentResolver(),
-                Settings.Global.ENABLE_TARE, null);
-        Settings.Global.putString(getApplicationContext().getContentResolver(),
-                Settings.Global.TARE_ALARM_MANAGER_CONSTANTS, null);
-        Settings.Global.putString(getApplicationContext().getContentResolver(),
-                Settings.Global.TARE_JOB_SCHEDULER_CONSTANTS, null);
-        if (wasSettingsDefault) {
-            // Only do this manually here to force a DeviceConfig check if the settings value isn't
-            // actually changing.
-            setEnabled(mConfigObserver.getDefaultEnabledStatus());
-        }
-    }
-
-    /** Opens up the AlarmManager TARE policy page with its factors to view and edit */
-    public void launchAlarmManagerPage(View v) {
-        Intent i = new Intent(getApplicationContext(), DropdownActivity.class);
-        i.putExtra(EXTRA_POLICY, POLICY_ALARM_MANAGER);
-        startActivity(i);
-    }
-
-    /** Opens up the JobScheduler TARE policy page with its factors to view and edit */
-    public void launchJobSchedulerPage(View v) {
-        Intent i = new Intent(getApplicationContext(), DropdownActivity.class);
-        i.putExtra(EXTRA_POLICY, POLICY_JOB_SCHEDULER);
-        startActivity(i);
-    }
-
-    /** Changes the enabled state of the TARE homepage buttons based on global toggle */
-    private void setEnabled(boolean tareStatus) {
-        mAlarmManagerView.setEnabled(tareStatus);
-        mJobSchedulerView.setEnabled(tareStatus);
-        mOnSwitch.setChecked(tareStatus);
-    }
-
-    private class ConfigObserver extends ContentObserver {
-        private int mEnableTareSetting;
-
-        ConfigObserver(Handler handler) {
-            super(handler);
-        }
-
-        public void start() {
-            getContentResolver().registerContentObserver(
-                    Settings.Global.getUriFor(Settings.Global.ENABLE_TARE), false, this);
-            processEnableTareChange();
-        }
-
-        public void stop() {
-            getContentResolver().unregisterContentObserver(this);
-        }
-
-        @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            processEnableTareChange();
-        }
-
-        private void processEnableTareChange() {
-            final String setting =
-                    Settings.Global.getString(getContentResolver(), Settings.Global.ENABLE_TARE);
-            if (setting == null) {
-                mEnableTareSetting = SETTING_VALUE_DEFAULT;
-            } else {
-                try {
-                    mEnableTareSetting = Integer.parseInt(setting);
-                } catch (NumberFormatException e) {
-                    Log.e(TAG, "Invalid setting value", e);
-                    mEnableTareSetting = EconomyManager.DEFAULT_ENABLE_TARE_MODE;
-                }
-            }
-            final boolean enabled;
-            if (mEnableTareSetting == SETTING_VALUE_ON) {
-                enabled = true;
-            } else if (mEnableTareSetting == SETTING_VALUE_OFF) {
-                enabled = false;
-            } else {
-                enabled = getDefaultEnabledStatus();
-            }
-            setEnabled(enabled);
-        }
-
-        private boolean getDefaultEnabledStatus() {
-            // Show Shadow Mode as "off" in the UI since it won't be affecting device behavior.
-            return DeviceConfig.getInt(DeviceConfig.NAMESPACE_TARE,
-                    EconomyManager.KEY_ENABLE_TARE_MODE,
-                    EconomyManager.DEFAULT_ENABLE_TARE_MODE) == EconomyManager.ENABLED_MODE_ON;
-        }
-    }
-}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java
index 4b65cc9..ddb8ecb 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java
@@ -40,6 +40,7 @@
 import com.android.settings.R;
 import com.android.settings.fuelgauge.BatteryUtils;
 import com.android.settingslib.Utils;
+import com.android.settingslib.utils.StringUtil;
 
 import java.util.Comparator;
 import java.util.Locale;
@@ -655,4 +656,46 @@
             return 0.0d;
         }
     }
+
+    @Override
+    public String toString() {
+        return new StringBuilder()
+                .append("BatteryEntry{")
+                .append(String.format("\n\tname=%s isHidden=%b", mName, mIsHidden))
+                .append(String.format("\n\tconsume=%.2f%% | %f", mPercent, mConsumedPower))
+                .append(
+                        String.format(
+                                "\n\tconsume power= foreground:%f foregroundService:%f",
+                                mConsumedPowerInForeground, mConsumedPowerInForegroundService))
+                .append(
+                        String.format(
+                                "\n\tconsume power= background:%f cached:%f",
+                                mConsumedPowerInBackground, mConsumedPowerInCached))
+                .append(
+                        String.format(
+                                "\n\ttime= foreground:%s foregroundService:%s "
+                                        + "background:%s usageDuration:%s",
+                                StringUtil.formatElapsedTime(
+                                        mContext,
+                                        (double) mTimeInForegroundMs,
+                                        /* withSeconds= */ true,
+                                        /* collapseTimeUnit= */ false),
+                                StringUtil.formatElapsedTime(
+                                        mContext,
+                                        (double) mTimeInForegroundServiceMs,
+                                        /* withSeconds= */ true,
+                                        /* collapseTimeUnit= */ false),
+                                StringUtil.formatElapsedTime(
+                                        mContext,
+                                        (double) mTimeInBackgroundMs,
+                                        /* withSeconds= */ true,
+                                        /* collapseTimeUnit= */ false),
+                                StringUtil.formatElapsedTime(
+                                        mContext,
+                                        (double) mUsageDurationMs,
+                                        /* withSeconds= */ true,
+                                        /* collapseTimeUnit= */ false)))
+                .append(String.format("\n\tpackage:%s uid:%d", mDefaultPackageName, mUid))
+                .toString();
+    }
 }
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntry.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntry.java
index b42d373..dbe98bc 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntry.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntry.java
@@ -192,41 +192,44 @@
     @Override
     public String toString() {
         final String recordAtDateTime = ConvertUtils.utcToLocalTimeForLogging(mTimestamp);
-        final StringBuilder builder = new StringBuilder();
-        builder.append("\nBatteryHistEntry{");
-        builder.append(
-                String.format(
-                        "\n\tpackage=%s|label=%s|uid=%d|userId=%d|isHidden=%b",
-                        mPackageName, mAppLabel, mUid, mUserId, mIsHidden));
-        builder.append(
-                String.format(
-                        "\n\ttimestamp=%s|zoneId=%s|bootTimestamp=%d",
-                        recordAtDateTime, mZoneId, TimestampUtils.getSeconds(mBootTimestamp)));
-        builder.append(
-                String.format(
-                        "\n\tusage=%f|total=%f|consume=%f",
-                        mPercentOfTotal, mTotalPower, mConsumePower));
-        builder.append(
-                String.format(
-                        "\n\tforeground=%f|foregroundService=%f",
-                        mForegroundUsageConsumePower, mForegroundServiceUsageConsumePower));
-        builder.append(
-                String.format(
-                        "\n\tbackground=%f|cached=%f",
-                        mBackgroundUsageConsumePower, mCachedUsageConsumePower));
-        builder.append(
-                String.format(
-                        "\n\telapsedTime,fg=%d|fgs=%d|bg=%d",
-                        TimestampUtils.getSeconds(mBackgroundUsageTimeInMs),
-                        TimestampUtils.getSeconds(mForegroundServiceUsageTimeInMs),
-                        TimestampUtils.getSeconds(mBackgroundUsageTimeInMs)));
-        builder.append(
-                String.format("\n\tdrainType=%d|consumerType=%d", mDrainType, mConsumerType));
-        builder.append(
-                String.format(
-                        "\n\tbattery=%d|status=%d|health=%d\n}",
-                        mBatteryLevel, mBatteryStatus, mBatteryHealth));
-        return builder.toString();
+        return new StringBuilder()
+                .append("\nBatteryHistEntry{")
+                .append(
+                        String.format(
+                                "\n\tpackage=%s|label=%s|uid=%d|userId=%d|isHidden=%b",
+                                mPackageName, mAppLabel, mUid, mUserId, mIsHidden))
+                .append(
+                        String.format(
+                                "\n\ttimestamp=%s|zoneId=%s|bootTimestamp=%d",
+                                recordAtDateTime,
+                                mZoneId,
+                                TimestampUtils.getSeconds(mBootTimestamp)))
+                .append(
+                        String.format(
+                                "\n\tusage=%f|total=%f|consume=%f",
+                                mPercentOfTotal, mTotalPower, mConsumePower))
+                .append(
+                        String.format(
+                                "\n\tforeground=%f|foregroundService=%f",
+                                mForegroundUsageConsumePower, mForegroundServiceUsageConsumePower))
+                .append(
+                        String.format(
+                                "\n\tbackground=%f|cached=%f",
+                                mBackgroundUsageConsumePower, mCachedUsageConsumePower))
+                .append(
+                        String.format(
+                                "\n\telapsedTime,fg=%d|fgs=%d|bg=%d",
+                                TimestampUtils.getSeconds(mForegroundUsageTimeInMs),
+                                TimestampUtils.getSeconds(mForegroundServiceUsageTimeInMs),
+                                TimestampUtils.getSeconds(mBackgroundUsageTimeInMs)))
+                .append(
+                        String.format(
+                                "\n\tdrainType=%d|consumerType=%d", mDrainType, mConsumerType))
+                .append(
+                        String.format(
+                                "\n\tbattery=%d|status=%d|health=%d\n}",
+                                mBatteryLevel, mBatteryStatus, mBatteryHealth))
+                .toString();
     }
 
     private int getInteger(ContentValues values, String key) {
diff --git a/src/com/android/settings/gestures/SystemNavigationGestureSettings.java b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
index 4e35460..cfaee00 100644
--- a/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
+++ b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
@@ -41,6 +41,7 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.PreferenceScreen;
 
+import com.android.internal.accessibility.common.ShortcutConstants;
 import com.android.settings.R;
 import com.android.settings.accessibility.AccessibilityShortcutsTutorial;
 import com.android.settings.core.BasePreferenceController;
@@ -366,7 +367,7 @@
     private boolean isAnyServiceSupportAccessibilityButton() {
         final AccessibilityManager ams = getContext().getSystemService(AccessibilityManager.class);
         final List<String> targets = ams.getAccessibilityShortcutTargets(
-                AccessibilityManager.ACCESSIBILITY_BUTTON);
+                ShortcutConstants.UserShortcutType.SOFTWARE);
         return !targets.isEmpty();
     }
 
diff --git a/src/com/android/settings/network/apn/ApnTypes.kt b/src/com/android/settings/network/apn/ApnTypes.kt
index 2c8fa2a..d384625 100644
--- a/src/com/android/settings/network/apn/ApnTypes.kt
+++ b/src/com/android/settings/network/apn/ApnTypes.kt
@@ -109,11 +109,15 @@
         return regularOptions.filter { it.selected.value }.joinToString(",") { it.text }
     }
 
-    private val NotPreSelectedTypes = setOf(
-        ApnSetting.TYPE_IMS_STRING,
-        ApnSetting.TYPE_IA_STRING,
-        ApnSetting.TYPE_EMERGENCY_STRING,
-        ApnSetting.TYPE_MCX_STRING,
+    private val PreSelectedTypes = setOf(
+        ApnSetting.TYPE_DEFAULT_STRING,
+        ApnSetting.TYPE_MMS_STRING,
+        ApnSetting.TYPE_SUPL_STRING,
+        ApnSetting.TYPE_DUN_STRING,
+        ApnSetting.TYPE_HIPRI_STRING,
+        ApnSetting.TYPE_FOTA_STRING,
+        ApnSetting.TYPE_CBS_STRING,
+        ApnSetting.TYPE_XCAP_STRING,
     )
 
     fun getPreSelectedApnType(customizedConfig: CustomizedConfig): String =
@@ -123,5 +127,5 @@
 
     private fun defaultPreSelectedApnTypes(readOnlyApnTypes: List<String>) =
         if (ApnSetting.TYPE_ALL_STRING in readOnlyApnTypes) emptyList()
-        else APN_TYPES.filter { it !in readOnlyApnTypes + NotPreSelectedTypes }
+        else PreSelectedTypes.filterNot { it in readOnlyApnTypes }
 }
diff --git a/src/com/android/settings/widget/HighlightablePreferenceGroupAdapter.java b/src/com/android/settings/widget/HighlightablePreferenceGroupAdapter.java
index 7145460..82ef58b 100644
--- a/src/com/android/settings/widget/HighlightablePreferenceGroupAdapter.java
+++ b/src/com/android/settings/widget/HighlightablePreferenceGroupAdapter.java
@@ -40,6 +40,7 @@
 
 import com.android.settings.R;
 import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.accessibility.AccessibilityUtil;
 
 import com.google.android.material.appbar.AppBarLayout;
 
@@ -50,6 +51,8 @@
     static final long DELAY_COLLAPSE_DURATION_MILLIS = 300L;
     @VisibleForTesting
     static final long DELAY_HIGHLIGHT_DURATION_MILLIS = 600L;
+    @VisibleForTesting
+    static final long DELAY_HIGHLIGHT_DURATION_MILLIS_A11Y = 300L;
     private static final long HIGHLIGHT_DURATION = 15000L;
     private static final long HIGHLIGHT_FADE_OUT_DURATION = 500L;
     private static final long HIGHLIGHT_FADE_IN_DURATION = 200L;
@@ -59,6 +62,7 @@
     @VisibleForTesting
     boolean mFadeInAnimated;
 
+    private final Context mContext;
     private final int mNormalBackgroundRes;
     private final String mHighlightKey;
     private boolean mHighlightRequested;
@@ -102,12 +106,12 @@
         super(preferenceGroup);
         mHighlightKey = key;
         mHighlightRequested = highlightRequested;
-        final Context context = preferenceGroup.getContext();
+        mContext = preferenceGroup.getContext();
         final TypedValue outValue = new TypedValue();
-        context.getTheme().resolveAttribute(android.R.attr.selectableItemBackground,
+        mContext.getTheme().resolveAttribute(android.R.attr.selectableItemBackground,
                 outValue, true /* resolveRefs */);
         mNormalBackgroundRes = outValue.resourceId;
-        mHighlightColor = context.getColor(R.color.preference_highlight_color);
+        mHighlightColor = mContext.getColor(R.color.preference_highlight_color);
     }
 
     @Override
@@ -121,12 +125,11 @@
         View v = holder.itemView;
         if (position == mHighlightPosition
                 && (mHighlightKey != null
-                && TextUtils.equals(mHighlightKey, getItem(position).getKey()))) {
+                && TextUtils.equals(mHighlightKey, getItem(position).getKey()))
+                && v.isShown()) {
             // This position should be highlighted. If it's highlighted before - skip animation.
+            v.requestAccessibilityFocus();
             addHighlightBackground(holder, !mFadeInAnimated);
-            if (v != null) {
-                v.requestAccessibilityFocus();
-            }
         } else if (Boolean.TRUE.equals(v.getTag(R.id.preference_highlighted))) {
             // View with highlight is reused for a view that should not have highlight
             removeHighlightBackground(holder, false /* animate */);
@@ -157,13 +160,14 @@
 
         // Remove the animator as early as possible to avoid a RecyclerView crash.
         recyclerView.setItemAnimator(null);
-        // Scroll to correct position after 600 milliseconds.
+        // Scroll to correct position after a short delay.
         root.postDelayed(() -> {
             if (ensureHighlightPosition()) {
                 recyclerView.smoothScrollToPosition(mHighlightPosition);
                 highlightAndFocusTargetItem(recyclerView, mHighlightPosition);
             }
-        }, DELAY_HIGHLIGHT_DURATION_MILLIS);
+        }, AccessibilityUtil.isTouchExploreEnabled(mContext)
+                ? DELAY_HIGHLIGHT_DURATION_MILLIS_A11Y : DELAY_HIGHLIGHT_DURATION_MILLIS);
     }
 
     private void highlightAndFocusTargetItem(RecyclerView recyclerView, int highlightPosition) {
diff --git a/tests/robotests/src/com/android/settings/SettingsActivityTest.java b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
index a879695..89f8449 100644
--- a/tests/robotests/src/com/android/settings/SettingsActivityTest.java
+++ b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
@@ -27,7 +27,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.app.ActionBar;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.Intent;
@@ -115,15 +114,6 @@
         assertThat(((ListenerFragment) fragments.get(1)).mOnActivityResultCalled).isTrue();
     }
 
-    @Test
-    public void getActionBar_hasNoActionBar() {
-        final SettingsActivity activity = Robolectric.buildActivity(SettingsActivity.class).get();
-
-        final ActionBar actionBar = activity.getActionBar();
-
-        assertThat(actionBar).isNull();
-    }
-
     public static class ListenerFragment extends Fragment implements OnActivityResultListener {
 
         private boolean mOnActivityResultCalled;
diff --git a/tests/robotests/src/com/android/settings/UtilsTest.java b/tests/robotests/src/com/android/settings/UtilsTest.java
index a4b0105..0c555da 100644
--- a/tests/robotests/src/com/android/settings/UtilsTest.java
+++ b/tests/robotests/src/com/android/settings/UtilsTest.java
@@ -30,6 +30,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.ActionBar;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyResourcesManager;
 import android.content.ComponentName;
@@ -55,9 +56,11 @@
 import android.os.storage.VolumeInfo;
 import android.util.IconDrawableFactory;
 import android.widget.EditText;
+import android.widget.ScrollView;
 import android.widget.TextView;
 
 import androidx.core.graphics.drawable.IconCompat;
+import androidx.fragment.app.FragmentActivity;
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
@@ -68,6 +71,7 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
@@ -267,6 +271,17 @@
     }
 
     @Test
+    public void setActionBarShadowAnimation_shouldSetElevationToZero() {
+        final FragmentActivity activity = Robolectric.setupActivity(FragmentActivity.class);
+        final ActionBar actionBar = activity.getActionBar();
+
+        Utils.setActionBarShadowAnimation(activity, activity.getLifecycle(),
+                new ScrollView(mContext));
+
+        assertThat(actionBar.getElevation()).isEqualTo(0.f);
+    }
+
+    @Test
     public void isSettingsIntelligence_IsSI_returnTrue() {
         final String siPackageName = mContext.getString(
                 R.string.config_settingsintelligence_package_name);
diff --git a/tests/robotests/src/com/android/settings/accessibility/ContrastPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/ContrastPreferenceControllerTest.java
index 219f3d9..07c3b54 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ContrastPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ContrastPreferenceControllerTest.java
@@ -18,17 +18,11 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import android.content.Context;
-import android.platform.test.flag.junit.CheckFlagsRule;
-import android.platform.test.flag.junit.DeviceFlagsValueProvider;
-import android.platform.test.flag.junit.SetFlagsRule;
-
 import androidx.test.core.app.ApplicationProvider;
 
 import com.android.settings.core.BasePreferenceController;
 
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
@@ -37,34 +31,19 @@
 @RunWith(RobolectricTestRunner.class)
 public class ContrastPreferenceControllerTest {
 
-    @Rule
-    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
-    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
-
     private static final String PREFERENCE_KEY = "preference_key";
 
-    private Context mContext;
     private ContrastPreferenceController mController;
 
     @Before
     public void setUp() {
-        mContext = ApplicationProvider.getApplicationContext();
-        mController = new ContrastPreferenceController(mContext, PREFERENCE_KEY);
+        mController = new ContrastPreferenceController(ApplicationProvider.getApplicationContext(),
+                PREFERENCE_KEY);
     }
 
     @Test
-    public void getAvailabilityStatus_flagsEnabled_shouldReturnAvailable() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_COLOR_CONTRAST_CONTROL);
-
+    public void getAvailabilityStatus_shouldReturnUnavailable() {
         assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.AVAILABLE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_flagsDisabled_shouldReturnUnsupported() {
-        mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_COLOR_CONTRAST_CONTROL);
-
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
+                .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/accessibility/PreviewSizeSeekBarControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/PreviewSizeSeekBarControllerTest.java
index af72beb..05273fc 100644
--- a/tests/robotests/src/com/android/settings/accessibility/PreviewSizeSeekBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/PreviewSizeSeekBarControllerTest.java
@@ -30,9 +30,6 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.os.Bundle;
-import android.platform.test.annotations.RequiresFlagsEnabled;
-import android.platform.test.flag.junit.CheckFlagsRule;
-import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.view.LayoutInflater;
 import android.widget.PopupWindow;
 import android.widget.SeekBar;
@@ -73,9 +70,6 @@
 public class PreviewSizeSeekBarControllerTest {
 
     @Rule
-    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
-
-    @Rule
     public ActivityScenarioRule<EmptyFragmentActivity> rule =
             new ActivityScenarioRule<>(EmptyFragmentActivity.class);
     private static final String FONT_SIZE_KEY = "font_size";
@@ -213,7 +207,6 @@
     }
 
     @Test
-    @RequiresFlagsEnabled(Flags.FLAG_REMOVE_QS_TOOLTIP_IN_SUW)
     public void onProgressChanged_inSuw_toolTipShouldNotShown() {
         Intent intent = mContext.getIntent();
         intent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true);
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
index 3d0f223..af94723 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
@@ -339,7 +339,6 @@
     }
 
     @Test
-    @EnableFlags(com.android.settings.accessibility.Flags.FLAG_REMOVE_QS_TOOLTIP_IN_SUW)
     @Config(shadows = ShadowFragment.class)
     public void onPreferenceToggledOnEnabledService_inSuw_toolTipViewShouldNotShow() {
         Intent suwIntent = new Intent();
diff --git a/tests/robotests/src/com/android/settings/biometrics/activeunlock/ActiveUnlockContentListenerTest.java b/tests/robotests/src/com/android/settings/biometrics/activeunlock/ActiveUnlockContentListenerTest.java
index 4da8151..8dd6199 100644
--- a/tests/robotests/src/com/android/settings/biometrics/activeunlock/ActiveUnlockContentListenerTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/activeunlock/ActiveUnlockContentListenerTest.java
@@ -19,6 +19,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 import static org.robolectric.shadows.ShadowLooper.idleMainLooper;
@@ -44,8 +45,6 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
-import java.util.ArrayList;
-
 @RunWith(RobolectricTestRunner.class)
 @Config(shadows = {ShadowDeviceConfig.class})
 public class ActiveUnlockContentListenerTest {
@@ -141,8 +140,7 @@
 
     @Test
     public void noProvider_subscribeDoesntRegisterObserver() {
-        when(mPackageManager.getInstalledPackages(any()))
-                .thenReturn(new ArrayList<>());
+        when(mPackageManager.resolveContentProvider(anyString(), any())).thenReturn(null);
         OnContentChangedListener listener = new OnContentChangedListener() {
             @Override
             public void onContentChanged(String newValue) {}
diff --git a/tests/robotests/src/com/android/settings/testutils/ActiveUnlockTestUtils.java b/tests/robotests/src/com/android/settings/testutils/ActiveUnlockTestUtils.java
index 06ca05c..e932280 100644
--- a/tests/robotests/src/com/android/settings/testutils/ActiveUnlockTestUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/ActiveUnlockTestUtils.java
@@ -18,12 +18,12 @@
 
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
@@ -32,8 +32,6 @@
 
 import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils;
 
-import java.util.ArrayList;
-
 /** Utilities class to enable or disable the Active Unlock flag in tests. */
 public final class ActiveUnlockTestUtils {
 
@@ -61,15 +59,10 @@
         resolveInfo.activityInfo.applicationInfo = applicationInfo;
         when(packageManager.resolveActivity(any(), anyInt())).thenReturn(resolveInfo);
 
-        PackageInfo packageInfo = new PackageInfo();
-        packageInfo.applicationInfo = applicationInfo;
         ProviderInfo providerInfo = new ProviderInfo();
         providerInfo.authority = PROVIDER;
         providerInfo.applicationInfo = applicationInfo;
-        packageInfo.providers = new ProviderInfo[] { providerInfo };
-        ArrayList<PackageInfo> packageInfos = new ArrayList<>();
-        packageInfos.add(packageInfo);
-        when(packageManager.getInstalledPackages(any())).thenReturn(packageInfos);
+        when(packageManager.resolveContentProvider(anyString(), any())).thenReturn(providerInfo);
 
         DeviceConfig.setProperty(
                 DeviceConfig.NAMESPACE_REMOTE_AUTH,
diff --git a/tests/robotests/src/com/android/settings/widget/HighlightablePreferenceGroupAdapterTest.java b/tests/robotests/src/com/android/settings/widget/HighlightablePreferenceGroupAdapterTest.java
index 29560ab..03684ad 100644
--- a/tests/robotests/src/com/android/settings/widget/HighlightablePreferenceGroupAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/widget/HighlightablePreferenceGroupAdapterTest.java
@@ -33,6 +33,7 @@
 import android.graphics.drawable.ColorDrawable;
 import android.os.Bundle;
 import android.view.View;
+import android.view.accessibility.AccessibilityManager;
 
 import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
@@ -54,6 +55,8 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowAccessibilityManager;
 import org.robolectric.util.ReflectionHelpers;
 
 @RunWith(RobolectricTestRunner.class)
@@ -67,7 +70,7 @@
     @Mock
     private View mRoot;
     @Mock
-    private PreferenceCategory mPreferenceCatetory;
+    private PreferenceCategory mPreferenceCategory;
     @Mock
     private SettingsPreferenceFragment mFragment;
 
@@ -82,8 +85,8 @@
         mContext = RuntimeEnvironment.application;
         mPreference = new Preference(mContext);
         mPreference.setKey(TEST_KEY);
-        when(mPreferenceCatetory.getContext()).thenReturn(mContext);
-        mAdapter = spy(new HighlightablePreferenceGroupAdapter(mPreferenceCatetory, TEST_KEY,
+        when(mPreferenceCategory.getContext()).thenReturn(mContext);
+        mAdapter = spy(new HighlightablePreferenceGroupAdapter(mPreferenceCategory, TEST_KEY,
                 false /* highlighted*/));
         when(mAdapter.getItem(anyInt())).thenReturn(mPreference);
         mViewHolder = PreferenceViewHolder.createInstanceForTests(
@@ -102,6 +105,18 @@
     }
 
     @Test
+    public void requestHighlight_enableTouchExploration_shouldHaveA11yHighlightDelay() {
+        ShadowAccessibilityManager am = Shadow.extract(AccessibilityManager.getInstance(mContext));
+        am.setTouchExplorationEnabled(true);
+        when(mAdapter.getPreferenceAdapterPosition(anyString())).thenReturn(1);
+        mAdapter.requestHighlight(mRoot, mock(RecyclerView.class), mock(AppBarLayout.class));
+
+        // DELAY_HIGHLIGHT_DURATION_MILLIS_A11Y = DELAY_COLLAPSE_DURATION_MILLIS
+        verify(mRoot, times(2)).postDelayed(any(),
+                eq(HighlightablePreferenceGroupAdapter.DELAY_HIGHLIGHT_DURATION_MILLIS_A11Y));
+    }
+
+    @Test
     public void requestHighlight_noKey_highlightedBefore_noRecyclerView_shouldNotRequest() {
         ReflectionHelpers.setField(mAdapter, "mHighlightKey", null);
         ReflectionHelpers.setField(mAdapter, "mHighlightRequested", false);
@@ -178,12 +193,24 @@
         assertThat(mViewHolder.itemView.getTag(R.id.preference_highlighted)).isNull();
     }
 
+    @Test
+    public void updateBackground_itemViewIsInvisible_shouldNotSetHighlightedTag() {
+        ReflectionHelpers.setField(mAdapter, "mHighlightPosition", 10);
+        ReflectionHelpers.setField(mViewHolder, "itemView", spy(mViewHolder.itemView));
+        when(mViewHolder.itemView.isShown()).thenReturn(false);
+
+        mAdapter.updateBackground(mViewHolder, 0);
+
+        assertThat(mViewHolder.itemView.getTag(R.id.preference_highlighted)).isNull();
+    }
+
     /**
      * When background is being updated, we also request the a11y focus on the preference
      */
     @Test
     public void updateBackground_shouldRequestAccessibilityFocus() {
         View viewItem = mock(View.class);
+        when(viewItem.isShown()).thenReturn(true);
         mViewHolder = PreferenceViewHolder.createInstanceForTests(viewItem);
         ReflectionHelpers.setField(mAdapter, "mHighlightPosition", 10);
 
@@ -195,6 +222,8 @@
     @Test
     public void updateBackground_highlight_shouldAnimateBackgroundAndSetHighlightedTag() {
         ReflectionHelpers.setField(mAdapter, "mHighlightPosition", 10);
+        ReflectionHelpers.setField(mViewHolder, "itemView", spy(mViewHolder.itemView));
+        when(mViewHolder.itemView.isShown()).thenReturn(true);
         assertThat(mAdapter.mFadeInAnimated).isFalse();
 
         mAdapter.updateBackground(mViewHolder, 10);
@@ -206,9 +235,21 @@
     }
 
     @Test
+    public void updateBackground_highlight_itemViewIsInvisible_shouldNotAnimate() {
+        ReflectionHelpers.setField(mAdapter, "mHighlightPosition", 10);
+        ReflectionHelpers.setField(mViewHolder, "itemView", spy(mViewHolder.itemView));
+        when(mViewHolder.itemView.isShown()).thenReturn(false);
+
+        mAdapter.updateBackground(mViewHolder, 10);
+
+        assertThat(mAdapter.mFadeInAnimated).isFalse();
+    }
+
+    @Test
     public void updateBackgroundTwice_highlight_shouldAnimateOnce() {
         ReflectionHelpers.setField(mAdapter, "mHighlightPosition", 10);
         ReflectionHelpers.setField(mViewHolder, "itemView", spy(mViewHolder.itemView));
+        when(mViewHolder.itemView.isShown()).thenReturn(true);
         assertThat(mAdapter.mFadeInAnimated).isFalse();
         mAdapter.updateBackground(mViewHolder, 10);
         // mFadeInAnimated change from false to true - indicating background change is scheduled
diff --git a/tests/spa_unit/src/com/android/settings/datausage/lib/AppDataUsageDetailsRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/datausage/lib/AppDataUsageDetailsRepositoryTest.kt
index fda3dc9..8476a49 100644
--- a/tests/spa_unit/src/com/android/settings/datausage/lib/AppDataUsageDetailsRepositoryTest.kt
+++ b/tests/spa_unit/src/com/android/settings/datausage/lib/AppDataUsageDetailsRepositoryTest.kt
@@ -125,6 +125,32 @@
         )
     }
 
+    @Test
+    fun queryDetailsForCycles_appWithZeroUsage_filtered(): Unit = runBlocking {
+        networkStatsRepository.stub {
+            on { queryBuckets(CYCLE1_END_TIME, CYCLE2_END_TIME) } doReturn listOf(
+                Bucket(
+                    uid = UID,
+                    bytes = 0L,
+                    startTimeStamp = 0L,
+                    endTimeStamp = 0L,
+                ),
+            )
+        }
+        val repository = AppDataUsageDetailsRepository(
+            context = context,
+            cycles = null,
+            template = template,
+            uids = listOf(UID),
+            networkCycleDataRepository = networkCycleDataRepository,
+            networkStatsRepository = networkStatsRepository,
+        )
+
+        val detailsForCycles = repository.queryDetailsForCycles()
+
+        assertThat(detailsForCycles).isEmpty()
+    }
+
     private companion object {
         const val CYCLE1_START_TIME = 1694444444000L
         const val CYCLE1_END_TIME = 1695555555000L
diff --git a/tests/spa_unit/src/com/android/settings/network/apn/ApnTypesTest.kt b/tests/spa_unit/src/com/android/settings/network/apn/ApnTypesTest.kt
new file mode 100644
index 0000000..95471b0
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/apn/ApnTypesTest.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.apn
+
+import android.telephony.data.ApnSetting
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ApnTypesTest {
+
+    @Test
+    fun getPreSelectedApnType_regular() {
+        val apnType = ApnTypes.getPreSelectedApnType(CustomizedConfig())
+
+        assertThat(apnType).isEqualTo("default,mms,supl,dun,hipri,fota,cbs,xcap")
+    }
+
+    @Test
+    fun getPreSelectedApnType_readOnlyApnTypes() {
+        val customizedConfig = CustomizedConfig(
+            readOnlyApnTypes = listOf(ApnSetting.TYPE_DUN_STRING),
+        )
+
+        val apnType = ApnTypes.getPreSelectedApnType(customizedConfig)
+
+        assertThat(apnType).isEqualTo("default,mms,supl,hipri,fota,cbs,xcap")
+    }
+}
diff --git a/tests/unit/src/com/android/settings/MainClearTest.kt b/tests/unit/src/com/android/settings/MainClearTest.kt
index 05f06df..bfaafdd 100644
--- a/tests/unit/src/com/android/settings/MainClearTest.kt
+++ b/tests/unit/src/com/android/settings/MainClearTest.kt
@@ -28,11 +28,13 @@
 import com.android.settings.Settings.FactoryResetActivity
 import com.android.settings.flags.Flags
 import com.google.common.truth.Truth.assertThat
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 
 /** Test [MainClear]. */
+@Ignore
 @RunWith(AndroidJUnit4::class)
 class MainClearTest {
     @get:Rule
diff --git a/tests/unit/src/com/android/settings/testutils/ActiveUnlockTestUtils.java b/tests/unit/src/com/android/settings/testutils/ActiveUnlockTestUtils.java
index 06ca05c..e932280 100644
--- a/tests/unit/src/com/android/settings/testutils/ActiveUnlockTestUtils.java
+++ b/tests/unit/src/com/android/settings/testutils/ActiveUnlockTestUtils.java
@@ -18,12 +18,12 @@
 
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
@@ -32,8 +32,6 @@
 
 import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils;
 
-import java.util.ArrayList;
-
 /** Utilities class to enable or disable the Active Unlock flag in tests. */
 public final class ActiveUnlockTestUtils {
 
@@ -61,15 +59,10 @@
         resolveInfo.activityInfo.applicationInfo = applicationInfo;
         when(packageManager.resolveActivity(any(), anyInt())).thenReturn(resolveInfo);
 
-        PackageInfo packageInfo = new PackageInfo();
-        packageInfo.applicationInfo = applicationInfo;
         ProviderInfo providerInfo = new ProviderInfo();
         providerInfo.authority = PROVIDER;
         providerInfo.applicationInfo = applicationInfo;
-        packageInfo.providers = new ProviderInfo[] { providerInfo };
-        ArrayList<PackageInfo> packageInfos = new ArrayList<>();
-        packageInfos.add(packageInfo);
-        when(packageManager.getInstalledPackages(any())).thenReturn(packageInfos);
+        when(packageManager.resolveContentProvider(anyString(), any())).thenReturn(providerInfo);
 
         DeviceConfig.setProperty(
                 DeviceConfig.NAMESPACE_REMOTE_AUTH,