Merge "Hide "Long Background Tasks" page from Settings." into udc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 5904282..ff4096f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -3717,7 +3717,7 @@
         <!-- Show channel-level notification settings (channel passed in as extras) -->
         <activity android:name=".notification.app.ChannelPanelActivity"
                   android:label="@string/notification_channel_title"
-                  android:theme="@style/Theme.Panel"
+                  android:theme="@style/Theme.Panel.Material"
                   android:excludeFromRecents="true"
                   android:configChanges="keyboardHidden|screenSize"
                   android:exported="true">
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 836806c..4e85cb8 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -2,6 +2,20 @@
   "presubmit": [
     {
       "name": "SettingsSpaUnitTests"
+    },
+    {
+      "name": "SettingsUnitTests",
+      "options": [
+        {
+          "include-filter": "com.android.settings.password"
+        },
+        {
+          "include-filter": "com.android.settings.biometrics"
+        },
+        {
+          "include-filter": "com.android.settings.biometrics2"
+        }
+      ]
     }
   ],
   "postsubmit": [
diff --git a/res/drawable/button_border_selected.xml b/res/drawable/button_border_selected.xml
index 0cd4aa5..1402380 100644
--- a/res/drawable/button_border_selected.xml
+++ b/res/drawable/button_border_selected.xml
@@ -15,10 +15,7 @@
   limitations under the License.
   -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
-       xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
        android:shape="rectangle">
-    <solid
-        android:color="?androidprv:attr/materialColorSurfaceContainer" />
     <stroke
         android:width="2dp"
         android:color="?android:attr/colorAccent"/>
diff --git a/res/drawable/button_border_unselected.xml b/res/drawable/button_border_unselected.xml
index 2c2ef3d..d0ce75b 100644
--- a/res/drawable/button_border_unselected.xml
+++ b/res/drawable/button_border_unselected.xml
@@ -18,7 +18,7 @@
        android:shape="rectangle">
     <stroke
         android:width="1dp"
-        android:color="@color/notification_importance_button_unselected"/>
+        android:color="?android:attr/colorAccent"/>
 
     <corners android:radius="@dimen/rect_button_radius" />
 </shape>
diff --git a/res/drawable/checkbox_circle_shape.xml b/res/drawable/checkbox_circle_shape.xml
index 68c5a2e..51a567c 100644
--- a/res/drawable/checkbox_circle_shape.xml
+++ b/res/drawable/checkbox_circle_shape.xml
@@ -1,24 +1,31 @@
 <!--
-  ~ Copyright (C) 2023 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
+     Copyright (C) 2023 The Android Open Source Project
 
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
+     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.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
     <item
-        android:state_checked="true"
-        android:drawable="@drawable/ic_check_circle_filled_24dp" />
-    <item
-        android:state_checked="false"
-        android:drawable="@drawable/ic_circle_outline_24dp" />
-</selector>
\ No newline at end of file
+        android:bottom="12dp"
+        android:left="12dp"
+        android:right="12dp"
+        android:top="12dp">
+        <selector>
+            <item
+                android:state_checked="true"
+                android:drawable="@drawable/ic_check_circle_filled_24dp" />
+            <item
+                android:state_checked="false"
+                android:drawable="@drawable/ic_circle_outline_24dp" />
+        </selector>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/res/layout/choose_lock_password.xml b/res/layout/choose_lock_password.xml
index b748f94..5819774 100644
--- a/res/layout/choose_lock_password.xml
+++ b/res/layout/choose_lock_password.xml
@@ -74,7 +74,6 @@
                 android:layout_height="wrap_content"
                 android:layout_gravity="center_horizontal"
                 android:gravity="center"
-                android:paddingLeft="14dp"
                 android:text="@string/auto_pin_confirm_user_message"
                 android:textSize="16sp"
                 android:button="@drawable/checkbox_circle_shape"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 405960b..bad0dcc 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4243,7 +4243,7 @@
     <string name="accessibility_screen_magnification_follow_typing_title">Magnify typing</string>
     <!-- Summary for accessibility follow typing preference for magnification. [CHAR LIMIT=none] -->
     <string name="accessibility_screen_magnification_follow_typing_summary">Magnifier follows text as you type</string>
-    <!-- Title for accessibility magnifier preference where the magnifier never turns off while switching apps. [CHAR LIMIT=35] -->
+    <!-- Title for accessibility magnifier preference where the magnifier never turns off while switching apps. [CHAR LIMIT=60] -->
     <string name="accessibility_screen_magnification_always_on_title">Keep on while switching apps</string>
     <!-- Summary for accessibility magnifier preference where the magnifier never turns off while switching apps. [CHAR LIMIT=none] -->
     <string name="accessibility_screen_magnification_always_on_summary">Magnifier stays on and zooms out when you switch apps</string>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index eeba1c7..8f13279 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -227,6 +227,9 @@
         <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
     </style>
 
+    <style name="Theme.Panel.Material" parent="Theme.Panel" >
+        <item name="android:switchStyle">@style/Switch.SettingsLib</item>
+    </style>
     <!-- Material theme for the pages containing TabLayout and ViewPager -->
     <style name="Theme.TabTheme" parent="@style/Theme.MaterialComponents.DayNight">
         <item name="colorPrimary">@*android:color/edge_effect_device_default_light</item>
diff --git a/src/com/android/settings/applications/ClonedAppsPreferenceController.java b/src/com/android/settings/applications/ClonedAppsPreferenceController.java
index a8a79f4..332df18 100644
--- a/src/com/android/settings/applications/ClonedAppsPreferenceController.java
+++ b/src/com/android/settings/applications/ClonedAppsPreferenceController.java
@@ -75,6 +75,9 @@
     }
 
     private void updatePreferenceSummary() {
+        if (!isAvailable()) {
+            return;
+        }
         new AsyncTask<Void, Void, Integer[]>() {
 
             @Override
diff --git a/src/com/android/settings/fuelgauge/BatteryBackupHelper.java b/src/com/android/settings/fuelgauge/BatteryBackupHelper.java
index 1bb3b4d..66ffc90 100644
--- a/src/com/android/settings/fuelgauge/BatteryBackupHelper.java
+++ b/src/com/android/settings/fuelgauge/BatteryBackupHelper.java
@@ -25,17 +25,20 @@
 import android.content.SharedPreferences;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
+import android.os.Build;
 import android.os.IDeviceIdleController;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
 
 import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
 
 import java.io.IOException;
@@ -49,13 +52,22 @@
 public final class BatteryBackupHelper implements BackupHelper {
     /** An inditifier for {@link BackupHelper}. */
     public static final String TAG = "BatteryBackupHelper";
+    // Definition for the device build information.
+    public static final String KEY_BUILD_BRAND = "device_build_brand";
+    public static final String KEY_BUILD_PRODUCT = "device_build_product";
+    public static final String KEY_BUILD_MANUFACTURER = "device_build_manufacture";
+    public static final String KEY_BUILD_FINGERPRINT = "device_build_fingerprint";
+    // Customized fields for device extra information.
+    public static final String KEY_BUILD_METADATA_1 = "device_build_metadata_1";
+    public static final String KEY_BUILD_METADATA_2 = "device_build_metadata_2";
+
     private static final String DEVICE_IDLE_SERVICE = "deviceidle";
     private static final String BATTERY_OPTIMIZE_BACKUP_FILE_NAME =
             "battery_optimize_backup_historical_logs";
+    private static final int DEVICE_BUILD_INFO_SIZE = 6;
 
     static final String DELIMITER = ",";
     static final String DELIMITER_MODE = ":";
-    static final String KEY_FULL_POWER_LIST = "full_power_list";
     static final String KEY_OPTIMIZATION_LIST = "optimization_mode_list";
 
     @VisibleForTesting
@@ -70,7 +82,13 @@
     @VisibleForTesting
     BatteryOptimizeUtils mBatteryOptimizeUtils;
 
+    private byte[] mOptimizationModeBytes;
+    private boolean mVerifyMigrateConfiguration = false;
+
     private final Context mContext;
+    // Device information map from the restoreEntity() method.
+    private final ArrayMap<String, String> mDeviceBuildInfoMap =
+            new ArrayMap<>(DEVICE_BUILD_INFO_SIZE);
 
     public BatteryBackupHelper(Context context) {
         mContext = context.getApplicationContext();
@@ -83,41 +101,58 @@
             Log.w(TAG, "ignore performBackup() for non-owner or empty data");
             return;
         }
-        final List<String> allowlistedApps = backupFullPowerList(data);
-        if (allowlistedApps != null) {
-            backupOptimizationMode(data, allowlistedApps);
+        final List<String> allowlistedApps = getFullPowerList();
+        if (allowlistedApps == null) {
+            return;
         }
+
+        writeBackupData(data, KEY_BUILD_BRAND, Build.BRAND);
+        writeBackupData(data, KEY_BUILD_PRODUCT, Build.PRODUCT);
+        writeBackupData(data, KEY_BUILD_MANUFACTURER, Build.MANUFACTURER);
+        writeBackupData(data, KEY_BUILD_FINGERPRINT, Build.FINGERPRINT);
+        // Add customized device build metadata fields.
+        final PowerUsageFeatureProvider provider = FeatureFactory.getFactory(mContext)
+                .getPowerUsageFeatureProvider(mContext);
+        writeBackupData(data, KEY_BUILD_METADATA_1, provider.getBuildMetadata1(mContext));
+        writeBackupData(data, KEY_BUILD_METADATA_2, provider.getBuildMetadata2(mContext));
+
+        backupOptimizationMode(data, allowlistedApps);
     }
 
     @Override
     public void restoreEntity(BackupDataInputStream data) {
-        BatterySettingsMigrateChecker.verifySaverConfiguration(mContext);
+        // Ensure we only verify the migrate configuration one time.
+        if (!mVerifyMigrateConfiguration) {
+            mVerifyMigrateConfiguration = true;
+            BatterySettingsMigrateChecker.verifySaverConfiguration(mContext);
+        }
         if (!isOwner() || data == null || data.size() == 0) {
             Log.w(TAG, "ignore restoreEntity() for non-owner or empty data");
             return;
         }
-
-        if (KEY_OPTIMIZATION_LIST.equals(data.getKey())) {
-            final int dataSize = data.size();
-            final byte[] dataBytes = new byte[dataSize];
-            try {
-                data.read(dataBytes, 0 /*offset*/, dataSize);
-            } catch (IOException e) {
-                Log.e(TAG, "failed to load BackupDataInputStream", e);
-                return;
-            }
-            final int restoreCount = restoreOptimizationMode(dataBytes);
-            if (restoreCount > 0) {
-                BatterySettingsMigrateChecker.verifyOptimizationModes(mContext);
-            }
+        final String dataKey = data.getKey();
+        switch (dataKey) {
+            case KEY_BUILD_BRAND:
+            case KEY_BUILD_PRODUCT:
+            case KEY_BUILD_MANUFACTURER:
+            case KEY_BUILD_FINGERPRINT:
+            case KEY_BUILD_METADATA_1:
+            case KEY_BUILD_METADATA_2:
+                restoreBackupData(dataKey, data);
+                break;
+            case KEY_OPTIMIZATION_LIST:
+                // Hold the optimization mode data until all conditions are matched.
+                mOptimizationModeBytes = getBackupData(dataKey, data);
+                break;
         }
+        performRestoreIfNeeded();
     }
 
     @Override
     public void writeNewStateDescription(ParcelFileDescriptor newState) {
     }
 
-    private List<String> backupFullPowerList(BackupDataOutput data) {
+    private List<String> getFullPowerList() {
         final long timestamp = System.currentTimeMillis();
         String[] allowlistedApps;
         try {
@@ -131,10 +166,7 @@
             Log.w(TAG, "no data found in the getFullPowerList()");
             return new ArrayList<>();
         }
-
-        final String allowedApps = String.join(DELIMITER, allowlistedApps);
-        writeBackupData(data, KEY_FULL_POWER_LIST, allowedApps);
-        Log.d(TAG, String.format("backup getFullPowerList() size=%d in %d/ms",
+        Log.d(TAG, String.format("getFullPowerList() size=%d in %d/ms",
                 allowlistedApps.length, (System.currentTimeMillis() - timestamp)));
         return Arrays.asList(allowlistedApps);
     }
@@ -224,6 +256,23 @@
         return restoreCount;
     }
 
+    private void performRestoreIfNeeded() {
+        if (mOptimizationModeBytes == null || mOptimizationModeBytes.length == 0) {
+            return;
+        }
+        final PowerUsageFeatureProvider provider = FeatureFactory.getFactory(mContext)
+                .getPowerUsageFeatureProvider(mContext);
+        if (!provider.isValidToRestoreOptimizationMode(mDeviceBuildInfoMap)) {
+            return;
+        }
+        // Start to restore the app optimization mode data.
+        final int restoreCount = restoreOptimizationMode(mOptimizationModeBytes);
+        if (restoreCount > 0) {
+            BatterySettingsMigrateChecker.verifyOptimizationModes(mContext);
+        }
+        mOptimizationModeBytes = null; // clear data
+    }
+
     /** Dump the app optimization mode backup history data. */
     public static void dumpHistoricalData(Context context, PrintWriter writer) {
         BatteryHistoricalLogUtil.printBatteryOptimizeHistoricalLog(
@@ -303,8 +352,33 @@
         return BatteryOptimizeUtils.getInstalledApplications(mContext, getIPackageManager());
     }
 
+    private void restoreBackupData(String dataKey, BackupDataInputStream data) {
+        final byte[] dataBytes = getBackupData(dataKey, data);
+        if (dataBytes == null || dataBytes.length == 0) {
+            return;
+        }
+        final String dataContent = new String(dataBytes, StandardCharsets.UTF_8);
+        mDeviceBuildInfoMap.put(dataKey, dataContent);
+        Log.d(TAG, String.format("restore:%s:%s", dataKey, dataContent));
+    }
+
+    private static byte[] getBackupData(String dataKey, BackupDataInputStream data) {
+        final int dataSize = data.size();
+        final byte[] dataBytes = new byte[dataSize];
+        try {
+            data.read(dataBytes, 0 /*offset*/, dataSize);
+        } catch (IOException e) {
+            Log.e(TAG, "failed to getBackupData() " + dataKey, e);
+            return null;
+        }
+        return dataBytes;
+    }
+
     private static void writeBackupData(
             BackupDataOutput data, String dataKey, String dataContent) {
+        if (dataContent == null || dataContent.isEmpty()) {
+            return;
+        }
         final byte[] dataContentBytes = dataContent.getBytes();
         try {
             data.writeEntityHeader(dataKey, dataContentBytes.length);
@@ -312,5 +386,6 @@
         } catch (IOException e) {
             Log.e(TAG, "writeBackupData() is failed for " + dataKey, e);
         }
+        Log.d(TAG, String.format("backup:%s:%s", dataKey, dataContent));
     }
 }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
index 9f30473..0b0e243 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.util.ArrayMap;
 import android.util.SparseIntArray;
 
 import com.android.settingslib.fuelgauge.Estimate;
@@ -166,4 +167,19 @@
      * Returns {@link Set} for ignoring task root class names for screen on time
      */
     Set<String> getIgnoreScreenOnTimeTaskRootSet();
+
+    /**
+     * Returns the customized device build information for data backup
+     */
+    String getBuildMetadata1(Context context);
+
+    /**
+     * Returns the customized device build information for data backup
+     */
+    String getBuildMetadata2(Context context);
+
+    /**
+     * Whether the app optimization mode is valid to restore
+     */
+    boolean isValidToRestoreOptimizationMode(ArrayMap<String, String> deviceInfoMap);
 }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
index d65c212..1d0ba18 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -22,6 +22,7 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.os.Process;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.SparseIntArray;
 
@@ -188,4 +189,19 @@
     public Set<String> getIgnoreScreenOnTimeTaskRootSet() {
         return new ArraySet<>();
     }
+
+    @Override
+    public String getBuildMetadata1(Context context) {
+        return null;
+    }
+
+    @Override
+    public String getBuildMetadata2(Context context) {
+        return null;
+    }
+
+    @Override
+    public boolean isValidToRestoreOptimizationMode(ArrayMap<String, String> deviceInfoMap) {
+        return false;
+    }
 }
diff --git a/src/com/android/settings/regionalpreferences/FirstDayOfWeekController.java b/src/com/android/settings/regionalpreferences/FirstDayOfWeekController.java
index 1ebd166..574e62f 100644
--- a/src/com/android/settings/regionalpreferences/FirstDayOfWeekController.java
+++ b/src/com/android/settings/regionalpreferences/FirstDayOfWeekController.java
@@ -19,6 +19,8 @@
 import android.content.Context;
 import android.provider.Settings;
 
+import androidx.core.text.util.LocalePreferences;
+
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
 
diff --git a/src/com/android/settings/regionalpreferences/LocalePreferences.java b/src/com/android/settings/regionalpreferences/LocalePreferences.java
deleted file mode 100644
index 2006221..0000000
--- a/src/com/android/settings/regionalpreferences/LocalePreferences.java
+++ /dev/null
@@ -1,605 +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.regionalpreferences;
-import android.icu.number.LocalizedNumberFormatter;
-import android.icu.number.NumberFormatter;
-import android.icu.text.DateFormat;
-import android.icu.text.DateTimePatternGenerator;
-import android.icu.util.MeasureUnit;
-import android.os.Build.VERSION;
-
-import androidx.annotation.DoNotInline;
-import androidx.annotation.NonNull;
-import androidx.annotation.OptIn;
-import androidx.annotation.RestrictTo;
-import androidx.annotation.StringDef;
-import androidx.core.os.BuildCompat;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Locale;
-import java.util.Locale.Category;
-
-/**
- * TODO(b/263861083) This is a temp file and will replace it to Androidx version.
- * Provides friendly APIs to get the user's locale preferences. The data can refer to
- * external/cldr/common/main/en.xml.
- */
-public final class LocalePreferences {
-    private static final String TAG = LocalePreferences.class.getSimpleName();
-
-    /** APIs to get the user's preference of the hour cycle. */
-    public static class HourCycle {
-        private static final String U_EXTENSION_OF_HOUR_CYCLE = "hc";
-
-        /** 12 Hour System (0-11) */
-        public static final String H11 = "h11";
-        /** 12 Hour System (1-12) */
-        public static final String H12 = "h12";
-        /** 24 Hour System (0-23) */
-        public static final String H23 = "h23";
-        /** 24 Hour System (1-24) */
-        public static final String H24 = "h24";
-        /** Default hour cycle for the locale */
-        public static final String DEFAULT = "";
-
-        /** @hide */
-        @RestrictTo(RestrictTo.Scope.LIBRARY)
-        @StringDef({
-                H11,
-                H12,
-                H23,
-                H24,
-                DEFAULT
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface HourCycleTypes {
-        }
-
-        private HourCycle() {
-        }
-    }
-
-    /**
-     * Return the user's preference of the hour cycle which is from
-     * {@link Locale#getDefault(Locale.Category)}. The returned result is resolved and
-     * bases on the {@code Locale#getDefault(Locale.Category)}. E.g. "h23"
-     */
-    @NonNull
-    @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
-    @HourCycle.HourCycleTypes
-    public static String getHourCycle() {
-        return getHourCycle(true);
-    }
-
-    /**
-     * Return the hour cycle setting of the inputted {@link Locale}. The returned result is resolved
-     * and bases on the inputted {@code Locale}.
-     * E.g. "h23"
-     */
-    @NonNull
-    @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
-    @HourCycle.HourCycleTypes
-    public static String getHourCycle(@NonNull Locale locale) {
-        return getHourCycle(locale, true);
-    }
-
-    /**
-     * Return the user's preference of the hour cycle which is from
-     * {@link Locale#getDefault(Locale.Category)}. E.g. "h23"
-     *
-     * @param resolved If the {@code Locale#getDefault(Locale.Category)} contains hour cycle subtag,
-     *                 this argument is ignored. If the
-     *                 {@code Locale#getDefault(Locale.Category)} doesn't contain hour cycle subtag
-     *                 and the resolved argument is true, this function tries to find the default
-     *                 hour cycle for the {@code Locale#getDefault(Locale.Category)}. If the
-     *                 {@code Locale#getDefault(Locale.Category)} doesn't contain hour cycle subtag
-     *                 and the resolved argument is false, this function returns empty string
-     *                 i.e. HourCycle.Default.
-     * @return {@link HourCycle.HourCycleTypes} If the malformed hour cycle format was specified
-     * in the hour cycle subtag, e.g. en-US-u-hc-h32, this function returns empty string
-     * i.e. HourCycle.Default.
-     */
-    @NonNull
-    @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
-    @HourCycle.HourCycleTypes
-    public static String getHourCycle(
-            boolean resolved) {
-        return getHourCycle(Api33Impl.getDefaultLocale(), resolved);
-    }
-
-    /**
-     * Return the hour cycle setting of the inputted {@link Locale}. E.g. "en-US-u-hc-h23".
-     *
-     * @param locale   The {@code Locale} to get the hour cycle.
-     * @param resolved If the given {@code Locale} contains hour cycle subtag, this argument is
-     *                 ignored. If the given {@code Locale} doesn't contain hour cycle subtag and
-     *                 the resolved argument is true, this function tries to find the default
-     *                 hour cycle for the given {@code Locale}. If the given {@code Locale} doesn't
-     *                 contain hour cycle subtag and the resolved argument is false, this function
-     *                 return empty string i.e. HourCycle.Default.
-     * @return {@link HourCycle.HourCycleTypes} If the malformed hour cycle format was specified
-     * in the hour cycle subtag, e.g. en-US-u-hc-h32, this function returns empty string
-     * i.e. HourCycle.Default.
-     */
-    @NonNull
-    @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
-    @HourCycle.HourCycleTypes
-    public static String getHourCycle(@NonNull Locale locale, boolean resolved) {
-        if (!BuildCompat.isAtLeastT()) {
-            throw new IllegalArgumentException("not a valid extension: " + VERSION.SDK_INT);
-        }
-        return Api33Impl.getHourCycle(locale, resolved);
-    }
-
-    /** APIs to get the user's preference of Calendar. */
-    public static class CalendarType {
-        private static final String U_EXTENSION_OF_CALENDAR = "ca";
-        /** Chinese Calendar */
-        public static final String CHINESE = "chinese";
-        /** Dangi Calendar (Korea Calendar) */
-        public static final String DANGI = "dangi";
-        /** Gregorian Calendar */
-        public static final String GREGORIAN = "gregorian";
-        /** Hebrew Calendar */
-        public static final String HEBREW = "hebrew";
-        /** Indian National Calendar */
-        public static final String INDIAN = "indian";
-        /** Islamic Calendar */
-        public static final String ISLAMIC = "islamic";
-        /** Islamic Calendar (tabular, civil epoch) */
-        public static final String ISLAMIC_CIVIL = "islamic-civil";
-        /** Islamic Calendar (Saudi Arabia, sighting) */
-        public static final String ISLAMIC_RGSA = "islamic-rgsa";
-        /** Islamic Calendar (tabular, astronomical epoch) */
-        public static final String ISLAMIC_TBLA = "islamic-tbla";
-        /** Islamic Calendar (Umm al-Qura) */
-        public static final String ISLAMIC_UMALQURA = "islamic-umalqura";
-        /** Persian Calendar */
-        public static final String PERSIAN = "persian";
-        /** Default calendar for the locale */
-        public static final String DEFAULT = "";
-
-        /** @hide */
-        @RestrictTo(RestrictTo.Scope.LIBRARY)
-        @StringDef({
-                CHINESE,
-                DANGI,
-                GREGORIAN,
-                HEBREW,
-                INDIAN,
-                ISLAMIC,
-                ISLAMIC_CIVIL,
-                ISLAMIC_RGSA,
-                ISLAMIC_TBLA,
-                ISLAMIC_UMALQURA,
-                PERSIAN,
-                DEFAULT
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface CalendarTypes {
-        }
-
-        private CalendarType() {
-        }
-    }
-
-    /**
-     * Return the user's preference of the calendar type which is from {@link
-     * Locale#getDefault(Locale.Category)}. The returned result is resolved and bases on
-     * the {@code Locale#getDefault(Locale.Category)} settings. E.g. "chinese"
-     */
-    @NonNull
-    @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
-    @CalendarType.CalendarTypes
-    public static String getCalendarType() {
-        return getCalendarType(true);
-    }
-
-    /**
-     * Return the calendar type of the inputted {@link Locale}. The returned result is resolved and
-     * bases on the inputted {@link Locale} settings.
-     * E.g. "chinese"
-     */
-    @NonNull
-    @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
-    @CalendarType.CalendarTypes
-    public static String getCalendarType(@NonNull Locale locale) {
-        return getCalendarType(locale, true);
-    }
-
-    /**
-     * Return the user's preference of the calendar type which is from {@link
-     * Locale#getDefault(Locale.Category)}. E.g. "chinese"
-     *
-     * @param resolved If the {@code Locale#getDefault(Locale.Category)} contains calendar type
-     *                 subtag, this argument is ignored. If the
-     *                 {@code Locale#getDefault(Locale.Category)} doesn't contain calendar type
-     *                 subtag and the resolved argument is true, this function tries to find
-     *                 the default calendar type for the
-     *                 {@code Locale#getDefault(Locale.Category)}. If the
-     *                 {@code Locale#getDefault(Locale.Category)} doesn't contain calendar type
-     *                 subtag and the resolved argument is false, this function returns empty string
-     *                 i.e. CalendarTypes.Default.
-     * @return {@link CalendarType.CalendarTypes} If the malformed calendar type format was
-     * specified in the calendar type subtag, e.g. en-US-u-ca-calendar, this function returns
-     * empty string i.e. CalendarTypes.Default.
-     */
-    @NonNull
-    @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
-    @CalendarType.CalendarTypes
-    public static String getCalendarType(boolean resolved) {
-        return getCalendarType(Api33Impl.getDefaultLocale(), resolved);
-    }
-
-    /**
-     * Return the calendar type of the inputted {@link Locale}. E.g. "chinese"
-     *
-     * @param locale   The {@link Locale} to get the calendar type.
-     * @param resolved If the given {@code Locale} contains calendar type subtag, this argument is
-     *                 ignored. If the given {@code Locale} doesn't contain calendar type subtag and
-     *                 the resolved argument is true, this function tries to find the default
-     *                 calendar type for the given {@code Locale}. If the given {@code Locale}
-     *                 doesn't contain calendar type subtag and the resolved argument is false, this
-     *                 function return empty string i.e. CalendarTypes.Default.
-     * @return {@link CalendarType.CalendarTypes} If the malformed calendar type format was
-     * specified in the calendar type subtag, e.g. en-US-u-ca-calendar, this function returns
-     * empty string i.e. CalendarTypes.Default.
-     */
-    @NonNull
-    @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
-    @CalendarType.CalendarTypes
-    public static String getCalendarType(@NonNull Locale locale, boolean resolved) {
-        if (!BuildCompat.isAtLeastT()) {
-            throw new IllegalArgumentException("not a valid extension: " + VERSION.SDK_INT);
-        }
-        return Api33Impl.getCalendarType(locale, resolved);
-    }
-
-    /** APIs to get the user's preference of temperature unit. */
-    public static class TemperatureUnit {
-        private static final String U_EXTENSION_OF_TEMPERATURE_UNIT = "mu";
-        /** Celsius */
-        public static final String CELSIUS = "celsius";
-        /** Fahrenheit */
-        public static final String FAHRENHEIT = "fahrenhe";
-        /** Kelvin */
-        public static final String KELVIN = "kelvin";
-        /** Default Temperature for the locale */
-        public static final String DEFAULT = "";
-
-        /** @hide */
-        @RestrictTo(RestrictTo.Scope.LIBRARY)
-        @StringDef({
-                CELSIUS,
-                FAHRENHEIT,
-                KELVIN,
-                DEFAULT
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface TemperatureUnits {
-        }
-
-        private TemperatureUnit() {
-        }
-    }
-
-    /**
-     * Return the user's preference of the temperature unit which is from {@link
-     * Locale#getDefault(Locale.Category)}. The returned result is resolved and bases on the
-     * {@code Locale#getDefault(Locale.Category)} settings. E.g. "fahrenhe"
-     */
-    @NonNull
-    @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
-    @TemperatureUnit.TemperatureUnits
-    public static String getTemperatureUnit() {
-        return getTemperatureUnit(true);
-    }
-
-    /**
-     * Return the temperature unit of the inputted {@link Locale}. The returned result is resolved
-     * and bases on the inputted {@code Locale} settings. E.g. "fahrenhe"
-     */
-    @NonNull
-    @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
-    @TemperatureUnit.TemperatureUnits
-    public static String getTemperatureUnit(
-            @NonNull Locale locale) {
-        return getTemperatureUnit(locale, true);
-    }
-
-    /**
-     * Return the user's preference of the temperature unit which is from {@link
-     * Locale#getDefault(Locale.Category)}. E.g. "fahrenhe"
-     *
-     * @param resolved If the {@code Locale#getDefault(Locale.Category)} contains temperature unit
-     *                 subtag, this argument is ignored. If the
-     *                 {@code Locale#getDefault(Locale.Category)} doesn't contain temperature unit
-     *                 subtag and the resolved argument is true, this function tries to find
-     *                 the default temperature unit for the
-     *                 {@code Locale#getDefault(Locale.Category)}. If the
-     *                 {@code Locale#getDefault(Locale.Category)} doesn't contain temperature unit
-     *                 subtag and the resolved argument is false, this function returns empty string
-     *                 i.e. TemperatureUnits.Default.
-     * @return {@link TemperatureUnit.TemperatureUnits} If the malformed temperature unit format was
-     * specified in the temperature unit subtag, e.g. en-US-u-mu-temperature, this function returns
-     * empty string i.e. TemperatureUnits.Default.
-     */
-    @NonNull
-    @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
-    @TemperatureUnit.TemperatureUnits
-    public static String getTemperatureUnit(boolean resolved) {
-        return getTemperatureUnit(Api33Impl.getDefaultLocale(), resolved);
-    }
-
-    /**
-     * Return the temperature unit of the inputted {@link Locale}. E.g. "fahrenheit"
-     *
-     * @param locale   The {@link Locale} to get the temperature unit.
-     * @param resolved If the given {@code Locale} contains temperature unit subtag, this argument
-     *                 is ignored. If the given {@code Locale} doesn't contain temperature unit
-     *                 subtag and the resolved argument is true, this function tries to find
-     *                 the default temperature unit for the given {@code Locale}. If the given
-     *                 {@code Locale} doesn't contain temperature unit subtag and the resolved
-     *                 argument is false, this function return empty string
-     *                 i.e. TemperatureUnits.Default.
-     * @return {@link TemperatureUnit.TemperatureUnits} If the malformed temperature unit format was
-     * specified in the temperature unit subtag, e.g. en-US-u-mu-temperature, this function returns
-     * empty string i.e. TemperatureUnits.Default.
-     */
-    @NonNull
-    @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
-    @TemperatureUnit.TemperatureUnits
-    public static String getTemperatureUnit(@NonNull Locale locale, boolean resolved) {
-        if (!BuildCompat.isAtLeastT()) {
-            throw new IllegalArgumentException("not a valid extension: " + VERSION.SDK_INT);
-        }
-        return Api33Impl.getTemperatureUnit(locale, resolved);
-    }
-
-    /** APIs to get the user's preference of the first day of week. */
-    public static class FirstDayOfWeek {
-        private static final String U_EXTENSION_OF_FIRST_DAY_OF_WEEK = "fw";
-        /** Sunday */
-        public static final String SUNDAY = "sun";
-        /** Monday */
-        public static final String MONDAY = "mon";
-        /** Tuesday */
-        public static final String TUESDAY = "tue";
-        /** Wednesday */
-        public static final String WEDNESDAY = "wed";
-        /** Thursday */
-        public static final String THURSDAY = "thu";
-        /** Friday */
-        public static final String FRIDAY = "fri";
-        /** Saturday */
-        public static final String SATURDAY = "sat";
-        /** Default first day of week for the locale */
-        public static final String DEFAULT = "";
-
-        /** @hide */
-        @RestrictTo(RestrictTo.Scope.LIBRARY)
-        @StringDef({
-                SUNDAY,
-                MONDAY,
-                TUESDAY,
-                WEDNESDAY,
-                THURSDAY,
-                FRIDAY,
-                SATURDAY,
-                DEFAULT
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface Days {
-        }
-
-        private FirstDayOfWeek() {
-        }
-    }
-
-    /**
-     * Return the user's preference of the first day of week which is from
-     * {@link Locale#getDefault(Locale.Category)}. The returned result is resolved and bases on the
-     * {@code Locale#getDefault(Locale.Category)} settings. E.g. "sun"
-     */
-    @NonNull
-    @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
-    @FirstDayOfWeek.Days
-    public static String getFirstDayOfWeek() {
-        return getFirstDayOfWeek(true);
-    }
-
-    /**
-     * Return the first day of week of the inputted {@link Locale}. The returned result is resolved
-     * and bases on the inputted {@code Locale} settings.
-     * E.g. "sun"
-     */
-    @NonNull
-    @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
-    public static @FirstDayOfWeek.Days String getFirstDayOfWeek(@NonNull Locale locale) {
-        return getFirstDayOfWeek(locale, true);
-    }
-
-    /**
-     * Return the user's preference of the first day of week which is from {@link
-     * Locale#getDefault(Locale.Category)}. E.g. "sun"
-     *
-     * @param resolved If the {@code Locale#getDefault(Locale.Category)} contains first day of week
-     *                 subtag, this argument is ignored. If the
-     *                 {@code Locale#getDefault(Locale.Category)} doesn't contain first day of week
-     *                 subtag and the resolved argument is true, this function tries to find
-     *                 the default first day of week for the
-     *                 {@code Locale#getDefault(Locale.Category)}. If the
-     *                 {@code Locale#getDefault(Locale.Category)} doesn't contain first day of week
-     *                 subtag and the resolved argument is false, this function returns empty string
-     *                 i.e. Days.Default.
-     * @return {@link FirstDayOfWeek.Days} If the malformed first day of week format was specified
-     * in the first day of week subtag, e.g. en-US-u-fw-days, this function returns empty string
-     * i.e. Days.Default.
-     */
-    @NonNull
-    @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
-    @FirstDayOfWeek.Days
-    public static String getFirstDayOfWeek(boolean resolved) {
-        return getFirstDayOfWeek(Api33Impl.getDefaultLocale(), resolved);
-    }
-
-    /**
-     * Return the first day of week of the inputted {@link Locale}. E.g. "sun"
-     *
-     * @param locale   The {@link Locale} to get the first day of week.
-     * @param resolved If the given {@code Locale} contains first day of week subtag, this argument
-     *                 is ignored. If the given {@code Locale} doesn't contain first day of week
-     *                 subtag and the resolved argument is true, this function tries to find
-     *                 the default first day of week for the given {@code Locale}. If the given
-     *                 {@code Locale} doesn't contain first day of week subtag and the resolved
-     *                 argument is false, this function return empty string i.e. Days.Default.
-     * @return {@link FirstDayOfWeek.Days} If the malformed first day of week format was
-     * specified in the first day of week subtag, e.g. en-US-u-fw-days, this function returns
-     * empty string i.e. Days.Default.
-     */
-    @NonNull
-    @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
-    @FirstDayOfWeek.Days
-    public static String getFirstDayOfWeek(
-            @NonNull Locale locale, boolean resolved) {
-        if (!BuildCompat.isAtLeastT()) {
-            throw new IllegalArgumentException("not a valid extension: " + VERSION.SDK_INT);
-        }
-
-        return Api33Impl.getFirstDayOfWeek(locale, resolved);
-    }
-
-    private static class Api33Impl {
-        @DoNotInline
-        @HourCycle.HourCycleTypes
-        static String getHourCycle(@NonNull Locale locale,
-                boolean resolved) {
-            String hc = locale.getUnicodeLocaleType(HourCycle.U_EXTENSION_OF_HOUR_CYCLE);
-            if (hc != null) {
-                return hc;
-            }
-            if (!resolved) {
-                return HourCycle.DEFAULT;
-            }
-
-            return getHourCycleType(
-                    DateTimePatternGenerator.getInstance(locale).getDefaultHourCycle());
-
-        }
-
-        @DoNotInline
-        @CalendarType.CalendarTypes
-        static String getCalendarType(@NonNull Locale locale, boolean resolved) {
-            String ca = locale.getUnicodeLocaleType(CalendarType.U_EXTENSION_OF_CALENDAR);
-            if (ca != null) {
-                return ca;
-            }
-            if (!resolved) {
-                return CalendarType.DEFAULT;
-            }
-
-            return android.icu.util.Calendar.getInstance(locale).getType();
-        }
-
-        @DoNotInline
-        @TemperatureUnit.TemperatureUnits
-        static String getTemperatureUnit(@NonNull Locale locale, boolean resolved) {
-            String mu =
-                    locale.getUnicodeLocaleType(TemperatureUnit.U_EXTENSION_OF_TEMPERATURE_UNIT);
-            if (mu != null) {
-                return mu;
-            }
-            if (!resolved) {
-                return TemperatureUnit.DEFAULT;
-            }
-
-            return getResolvedTemperatureUnit(locale);
-        }
-
-        @DoNotInline
-        @FirstDayOfWeek.Days
-        static String getFirstDayOfWeek(@NonNull Locale locale, boolean resolved) {
-            String mu =
-                    locale.getUnicodeLocaleType(FirstDayOfWeek.U_EXTENSION_OF_FIRST_DAY_OF_WEEK);
-            if (mu != null) {
-                return mu;
-            }
-            if (!resolved) {
-                return FirstDayOfWeek.DEFAULT;
-            }
-            // TODO(b/262294472) Use {@code android.icu.util.Calendar} instead of
-            //  {@code java.util.Calendar}.
-            return getStringOfFirstDayOfWeek(
-                    java.util.Calendar.getInstance(locale).getFirstDayOfWeek());
-        }
-
-        @DoNotInline
-        static Locale getDefaultLocale() {
-            return Locale.getDefault(Category.FORMAT);
-        }
-
-        private static String getStringOfFirstDayOfWeek(int fw) {
-            String[] arrDays = {
-                    FirstDayOfWeek.SUNDAY,
-                    FirstDayOfWeek.MONDAY,
-                    FirstDayOfWeek.TUESDAY,
-                    FirstDayOfWeek.WEDNESDAY,
-                    FirstDayOfWeek.THURSDAY,
-                    FirstDayOfWeek.FRIDAY,
-                    FirstDayOfWeek.SATURDAY};
-
-            return fw >= 1 && fw <= 7 ? arrDays[fw - 1] : FirstDayOfWeek.DEFAULT;
-        }
-
-        @HourCycle.HourCycleTypes
-        private static String getHourCycleType(
-                DateFormat.HourCycle hourCycle) {
-            switch (hourCycle) {
-                case HOUR_CYCLE_11:
-                    return HourCycle.H11;
-                case HOUR_CYCLE_12:
-                    return HourCycle.H12;
-                case HOUR_CYCLE_23:
-                    return HourCycle.H23;
-                case HOUR_CYCLE_24:
-                    return HourCycle.H24;
-                default:
-                    return HourCycle.DEFAULT;
-            }
-        }
-
-        @TemperatureUnit.TemperatureUnits
-        private static String getResolvedTemperatureUnit(@NonNull Locale locale) {
-            LocalizedNumberFormatter nf = NumberFormatter.with()
-                    .usage("temperature")
-                    .unit(MeasureUnit.CELSIUS)
-                    .locale(locale);
-            String unit = nf.format(1).getOutputUnit().getIdentifier();
-            if (unit.contains(TemperatureUnit.FAHRENHEIT)) {
-                return TemperatureUnit.FAHRENHEIT;
-            }
-            return unit;
-        }
-
-        private Api33Impl() {
-        }
-    }
-
-    private LocalePreferences() {
-    }
-}
diff --git a/src/com/android/settings/regionalpreferences/RegionalPreferenceListBasePreferenceController.java b/src/com/android/settings/regionalpreferences/RegionalPreferenceListBasePreferenceController.java
index 823f5bb..1e39fff 100644
--- a/src/com/android/settings/regionalpreferences/RegionalPreferenceListBasePreferenceController.java
+++ b/src/com/android/settings/regionalpreferences/RegionalPreferenceListBasePreferenceController.java
@@ -63,7 +63,9 @@
             pref.setKey(item);
             pref.setOnPreferenceClickListener(clickedPref -> {
                 setSelected(pref);
-                RegionalPreferencesDataUtils.savePreference(mContext, getExtensionTypes(), item);
+                RegionalPreferencesDataUtils.savePreference(mContext, getExtensionTypes(),
+                        item.equals(RegionalPreferencesDataUtils.DEFAULT_VALUE)
+                                ? null : item);
                 mMetricsFeatureProvider.action(mContext, getMetricsActionKey());
                 return true;
             });
diff --git a/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtils.java b/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtils.java
index 32e00b4..d1ae40b 100644
--- a/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtils.java
+++ b/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtils.java
@@ -22,6 +22,8 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 
+import androidx.core.text.util.LocalePreferences;
+
 import com.android.internal.app.LocalePicker;
 import com.android.settings.R;
 
diff --git a/src/com/android/settings/regionalpreferences/TemperatureUnitController.java b/src/com/android/settings/regionalpreferences/TemperatureUnitController.java
index 9fbf69b..4b0f22c 100644
--- a/src/com/android/settings/regionalpreferences/TemperatureUnitController.java
+++ b/src/com/android/settings/regionalpreferences/TemperatureUnitController.java
@@ -19,6 +19,8 @@
 import android.content.Context;
 import android.provider.Settings;
 
+import androidx.core.text.util.LocalePreferences;
+
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
 
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
index 8970730..b8c72ee 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
@@ -28,6 +28,7 @@
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.inOrder;
@@ -45,6 +46,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.UserInfo;
+import android.os.Build;
 import android.os.IDeviceIdleController;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -53,6 +55,7 @@
 
 import com.android.settings.TestUtils;
 import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
+import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
 
 import org.junit.After;
@@ -89,6 +92,7 @@
     private PrintWriter mPrintWriter;
     private StringWriter mStringWriter;
     private BatteryBackupHelper mBatteryBackupHelper;
+    private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
 
     @Mock
     private PackageManager mPackageManager;
@@ -112,6 +116,8 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
+        mPowerUsageFeatureProvider =
+                FakeFeatureFactory.setupForTest().powerUsageFeatureProvider;
         mContext = spy(RuntimeEnvironment.application);
         mStringWriter = new StringWriter();
         mPrintWriter = new PrintWriter(mStringWriter);
@@ -136,19 +142,11 @@
     }
 
     @Test
-    public void performBackup_nullPowerList_notBackupPowerList() throws Exception {
-        doReturn(null).when(mDeviceController).getFullPowerWhitelist();
-        mBatteryBackupHelper.performBackup(null, mBackupDataOutput, null);
-
-        verify(mBackupDataOutput, never()).writeEntityHeader(anyString(), anyInt());
-    }
-
-    @Test
-    public void performBackup_emptyPowerList_notBackupPowerList() throws Exception {
+    public void performBackup_emptyPowerList_backupPowerList() throws Exception {
         doReturn(new String[0]).when(mDeviceController).getFullPowerWhitelist();
         mBatteryBackupHelper.performBackup(null, mBackupDataOutput, null);
 
-        verify(mBackupDataOutput, never()).writeEntityHeader(anyString(), anyInt());
+        verify(mBackupDataOutput, atLeastOnce()).writeEntityHeader(anyString(), anyInt());
     }
 
     @Test
@@ -160,34 +158,6 @@
     }
 
     @Test
-    public void performBackup_oneFullPowerListElement_backupFullPowerListData()
-            throws Exception {
-        final String[] fullPowerList = {"com.android.package"};
-        doReturn(fullPowerList).when(mDeviceController).getFullPowerWhitelist();
-
-        mBatteryBackupHelper.performBackup(null, mBackupDataOutput, null);
-
-        final byte[] expectedBytes = fullPowerList[0].getBytes();
-        verify(mBackupDataOutput).writeEntityHeader(
-                BatteryBackupHelper.KEY_FULL_POWER_LIST, expectedBytes.length);
-        verify(mBackupDataOutput).writeEntityData(expectedBytes, expectedBytes.length);
-    }
-
-    @Test
-    public void performBackup_backupFullPowerListData() throws Exception {
-        final String[] fullPowerList = {"com.android.package1", "com.android.package2"};
-        doReturn(fullPowerList).when(mDeviceController).getFullPowerWhitelist();
-
-        mBatteryBackupHelper.performBackup(null, mBackupDataOutput, null);
-
-        final String expectedResult = fullPowerList[0] + DELIMITER + fullPowerList[1];
-        final byte[] expectedBytes = expectedResult.getBytes();
-        verify(mBackupDataOutput).writeEntityHeader(
-                BatteryBackupHelper.KEY_FULL_POWER_LIST, expectedBytes.length);
-        verify(mBackupDataOutput).writeEntityData(expectedBytes, expectedBytes.length);
-    }
-
-    @Test
     public void performBackup_nonOwner_ignoreAllBackupAction() throws Exception {
         ShadowUserHandle.setUid(1);
         final String[] fullPowerList = {"com.android.package"};
@@ -283,7 +253,7 @@
 
     @Test
     public void restoreEntity_incorrectDataKey_notReadBackupData() throws Exception {
-        final String incorrectDataKey = BatteryBackupHelper.KEY_FULL_POWER_LIST;
+        final String incorrectDataKey = "incorrect_data_key";
         mockBackupData(30 /*dataSize*/, incorrectDataKey);
 
         mBatteryBackupHelper.restoreEntity(mBackupDataInputStream);
@@ -314,6 +284,20 @@
     }
 
     @Test
+    public void restoreEntity_verifyConfigurationOneTimeOnly() {
+        final int invalidScheduledLevel = 5;
+        TestUtils.setScheduledLevel(mContext, invalidScheduledLevel);
+        mBatteryBackupHelper.restoreEntity(mBackupDataInputStream);
+        TestUtils.setScheduledLevel(mContext, invalidScheduledLevel);
+
+        // Invoke the restoreEntity() method 2nd time.
+        mBatteryBackupHelper.restoreEntity(mBackupDataInputStream);
+
+        assertThat(TestUtils.getScheduledLevel(mContext))
+                .isEqualTo(invalidScheduledLevel);
+    }
+
+    @Test
     public void restoreOptimizationMode_nullBytesData_skipRestore() throws Exception {
         mBatteryBackupHelper.restoreOptimizationMode(new byte[0]);
         verifyNoInteractions(mBatteryOptimizeUtils);
@@ -358,6 +342,26 @@
                 .setAppUsageState(MODE_RESTRICTED, Action.RESTORE);
     }
 
+    @Test
+    public void performBackup_backupDeviceBuildInformation() throws Exception {
+        final String[] fullPowerList = {"com.android.package"};
+        doReturn(fullPowerList).when(mDeviceController).getFullPowerWhitelist();
+        doReturn(null).when(mPowerUsageFeatureProvider).getBuildMetadata1(mContext);
+        final String deviceMetadata = "device.metadata.test_device";
+        doReturn(deviceMetadata).when(mPowerUsageFeatureProvider).getBuildMetadata2(mContext);
+
+        mBatteryBackupHelper.performBackup(null, mBackupDataOutput, null);
+
+        final InOrder inOrder = inOrder(mBackupDataOutput);
+        verifyBackupData(inOrder, BatteryBackupHelper.KEY_BUILD_BRAND, Build.BRAND);
+        verifyBackupData(inOrder, BatteryBackupHelper.KEY_BUILD_PRODUCT, Build.PRODUCT);
+        verifyBackupData(inOrder, BatteryBackupHelper.KEY_BUILD_MANUFACTURER, Build.MANUFACTURER);
+        verifyBackupData(inOrder, BatteryBackupHelper.KEY_BUILD_FINGERPRINT, Build.FINGERPRINT);
+        inOrder.verify(mBackupDataOutput, never()).writeEntityHeader(
+                eq(BatteryBackupHelper.KEY_BUILD_METADATA_1), anyInt());
+        verifyBackupData(inOrder, BatteryBackupHelper.KEY_BUILD_METADATA_2, deviceMetadata);
+    }
+
     private void mockUid(int uid, String packageName) throws Exception {
         doReturn(uid).when(mPackageManager)
                 .getPackageUid(packageName, PackageManager.GET_META_DATA);
@@ -429,6 +433,13 @@
                 new ArraySet<>(Arrays.asList(applicationInfo1, applicationInfo2, applicationInfo3));
     }
 
+    private void verifyBackupData(
+            InOrder inOrder, String dataKey, String dataContent) throws Exception {
+        final byte[] expectedBytes = dataContent.getBytes();
+        inOrder.verify(mBackupDataOutput).writeEntityHeader(dataKey, expectedBytes.length);
+        inOrder.verify(mBackupDataOutput).writeEntityData(expectedBytes, expectedBytes.length);
+    }
+
     @Implements(UserHandle.class)
     public static class ShadowUserHandle {
         // Sets the default as thte OWNER role.
diff --git a/tests/unit/src/com/android/settings/biometrics/face/FaceUpdaterTest.java b/tests/unit/src/com/android/settings/biometrics/face/FaceUpdaterTest.java
index a49b4a6..66514ac 100644
--- a/tests/unit/src/com/android/settings/biometrics/face/FaceUpdaterTest.java
+++ b/tests/unit/src/com/android/settings/biometrics/face/FaceUpdaterTest.java
@@ -39,6 +39,7 @@
 import com.android.settings.safetycenter.SafetyCenterManagerWrapper;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -152,6 +153,7 @@
         verify(mSafetyCenterManagerWrapper, never()).isEnabled(any());
     }
 
+    @Ignore("b/282413778")
     @Test
     public void enroll_secondVersion_onEnrollmentCallbacks_triggerGivenCallback() {
         ArgumentCaptor<FaceManager.EnrollmentCallback> callbackCaptor =
@@ -180,6 +182,7 @@
                 .onEnrollmentFrame(HELP_CODE, HELP_MESSAGE, CELL, STAGE, PAN, TILT, DISTANCE);
     }
 
+    @Ignore("b/282413778")
     @Test
     public void enroll_secondVersion_onEnrollmentSuccess_invokedInteractionWithSafetyCenter() {
         ArgumentCaptor<FaceManager.EnrollmentCallback> callbackCaptor =
@@ -201,6 +204,7 @@
         verify(mSafetyCenterManagerWrapper).isEnabled(mContext);
     }
 
+    @Ignore("b/282413778")
     @Test
     public void enroll_secondVersion_onEnrollmentNotYetFinished_didntInvokeInteractionWithSafetyCenter() {
         ArgumentCaptor<FaceManager.EnrollmentCallback> callbackCaptor =
diff --git a/tests/unit/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtilsTest.java b/tests/unit/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtilsTest.java
index 85272e4..c9571be 100644
--- a/tests/unit/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtilsTest.java
+++ b/tests/unit/src/com/android/settings/regionalpreferences/RegionalPreferencesDataUtilsTest.java
@@ -22,6 +22,7 @@
 import android.os.LocaleList;
 import android.provider.Settings;
 
+import androidx.core.text.util.LocalePreferences;
 import androidx.test.core.app.ApplicationProvider;
 
 import com.android.internal.app.LocalePicker;