Merge "[Regional Preference] Set numbering system when select it" 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/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/layout/homepage_preference.xml b/res/layout/homepage_preference.xml
index 18ecdcf..f0b1b71 100644
--- a/res/layout/homepage_preference.xml
+++ b/res/layout/homepage_preference.xml
@@ -60,6 +60,8 @@
             android:id="@android:id/title"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:layout_gravity="start"
+            android:textAlignment="viewStart"
             android:singleLine="true"
             android:textAppearance="?android:attr/textAppearanceListItem"
             android:hyphenationFrequency="normalFast"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 405960b..1f3ba2a 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>
@@ -10158,7 +10158,9 @@
     <string name="financed_privacy_restrictions_removed">All restrictions are removed from the device</string>
     <!-- Label explaining that the app installed by credit provider can be uninstalled. [CHAR LIMIT=60]-->
     <string name="financed_privacy_uninstall_creditor_app">You can uninstall the creditor app</string>
-
+    <!-- Title of setting on security settings screen on a device provisioned by Device Lock. This will take the user to a screen in Device Lock with information about what a device provider can control and their impact on the user's privacy. Shown on Device Lock provisioned devices only. [CHAR LIMIT=NONE] -->
+    <!-- TODO(b/282040794): Update the title -->
+    <string name="device_lock_info">Device Lock</string>
     <!-- Strings for displaying which applications were set as default for specific actions. -->
     <!-- Title for the apps that have been set as default handlers of camera-related intents. [CHAR LIMIT=30] -->
     <string name="default_camera_app_title">{count, plural,
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/res/xml/app_info_settings.xml b/res/xml/app_info_settings.xml
index d8af009..73241b7 100644
--- a/res/xml/app_info_settings.xml
+++ b/res/xml/app_info_settings.xml
@@ -193,6 +193,8 @@
             android:key="long_background_tasks"
             android:title="@string/long_background_tasks_title"
             android:summary="@string/summary_placeholder"
+            settings:isPreferenceVisible="false"
+            settings:searchable="false"
             settings:controller="com.android.settings.applications.appinfo.LongBackgroundTasksDetailsPreferenceController" />
 
     </PreferenceCategory>
diff --git a/res/xml/more_security_privacy_settings.xml b/res/xml/more_security_privacy_settings.xml
index 5fce68f..1a9d788 100644
--- a/res/xml/more_security_privacy_settings.xml
+++ b/res/xml/more_security_privacy_settings.xml
@@ -146,6 +146,13 @@
             android:fragment="com.android.settings.enterprise.EnterprisePrivacySettings"
             settings:controller="com.android.settings.enterprise.FinancedPrivacyPreferenceController"/>
 
+        <Preference
+            android:key="device_lock_info"
+            android:title="@string/device_lock_info"
+            android:summary="@string/summary_placeholder"
+            settings:controller="com.android.settings.devicelock.DeviceLockPreferenceController">
+            <intent android:action="com.android.devicelockcontroller.action.DEVICE_INFO_SETTINGS"/>
+        </Preference>
     </PreferenceCategory>
 
     <Preference
diff --git a/res/xml/security_advanced_settings.xml b/res/xml/security_advanced_settings.xml
index 9856e84..8223f50 100644
--- a/res/xml/security_advanced_settings.xml
+++ b/res/xml/security_advanced_settings.xml
@@ -58,6 +58,13 @@
             android:fragment="com.android.settings.enterprise.EnterprisePrivacySettings"
             settings:controller="com.android.settings.enterprise.FinancedPrivacyPreferenceController"/>
 
+        <Preference
+            android:key="device_lock_info"
+            android:title="@string/device_lock_info"
+            android:summary="@string/summary_placeholder"
+            settings:controller="com.android.settings.devicelock.DeviceLockPreferenceController">
+            <intent android:action="com.android.devicelockcontroller.action.DEVICE_INFO_SETTINGS"/>
+        </Preference>
     </PreferenceCategory>
 
     <Preference
diff --git a/res/xml/special_access.xml b/res/xml/special_access.xml
index 2fb4af4..b3f3f7d 100644
--- a/res/xml/special_access.xml
+++ b/res/xml/special_access.xml
@@ -128,6 +128,8 @@
         android:title="@string/long_background_tasks_title"
         android:order="-800"
         android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
+        settings:isPreferenceVisible="false"
+        settings:searchable="false"
         settings:keywords="@string/keywords_long_background_tasks"
         settings:controller="com.android.settings.applications.specialaccess.applications.LongBackgroundTaskController">
         <extra
diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
index 07a737d..80d3947 100644
--- a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
+++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
@@ -16,10 +16,6 @@
 
 package com.android.settings.applications;
 
-import static android.Manifest.permission.RUN_USER_INITIATED_JOBS;
-import static android.app.AppOpsManager.OP_RUN_USER_INITIATED_JOBS;
-import static android.app.AppOpsManager.opToPermission;
-
 import android.Manifest;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
@@ -345,7 +341,9 @@
 
     @Override
     public boolean isLongBackgroundTaskPermissionToggleSupported() {
-        return TextUtils.equals(RUN_USER_INITIATED_JOBS,
-                opToPermission(OP_RUN_USER_INITIATED_JOBS));
+        // Since the RUN_USER_INITIATED_JOBS permission related to this controller is a normal
+        // app-op permission allowed by default, this should always return false - if it is ever
+        // converted to a special app-op permission, this should be updated.
+        return false;
     }
 }
diff --git a/src/com/android/settings/applications/specialaccess/applications/LongBackgroundTaskController.java b/src/com/android/settings/applications/specialaccess/applications/LongBackgroundTaskController.java
index 586980c..ccfa9c8 100644
--- a/src/com/android/settings/applications/specialaccess/applications/LongBackgroundTaskController.java
+++ b/src/com/android/settings/applications/specialaccess/applications/LongBackgroundTaskController.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * 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.
@@ -37,6 +37,6 @@
     @Override
     public int getAvailabilityStatus() {
         return mAppFeatureProvider.isLongBackgroundTaskPermissionToggleSupported()
-                ?  AVAILABLE : UNSUPPORTED_ON_DEVICE;
+                ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
     }
 }
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
index d0fb16a..5dabb7a 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
@@ -69,6 +69,7 @@
 
     private static final String ENABLE_DUAL_MODE_AUDIO =
             "persist.bluetooth.enable_dual_mode_audio";
+    private static final String CONFIG_LE_AUDIO_ENABLED_BY_DEFAULT = "le_audio_enabled_by_default";
 
     private LocalBluetoothManager mManager;
     private LocalBluetoothProfileManager mProfileManager;
@@ -99,7 +100,9 @@
         mIsLeContactSharingEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
                 SettingsUIDeviceConfig.BT_LE_AUDIO_CONTACT_SHARING_ENABLED, true);
         mIsLeAudioToggleEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
-                SettingsUIDeviceConfig.BT_LE_AUDIO_DEVICE_DETAIL_ENABLED, false);
+                SettingsUIDeviceConfig.BT_LE_AUDIO_DEVICE_DETAIL_ENABLED, false)
+                || DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_BLUETOOTH,
+                CONFIG_LE_AUDIO_ENABLED_BY_DEFAULT, false);
         // Call refresh here even though it will get called later in onResume, to avoid the
         // list of switches appearing to "pop" into the page.
         refresh();
diff --git a/src/com/android/settings/development/BluetoothLeAudioDeviceDetailsPreferenceController.java b/src/com/android/settings/development/BluetoothLeAudioDeviceDetailsPreferenceController.java
index 0945f0d..a54c594 100644
--- a/src/com/android/settings/development/BluetoothLeAudioDeviceDetailsPreferenceController.java
+++ b/src/com/android/settings/development/BluetoothLeAudioDeviceDetailsPreferenceController.java
@@ -39,6 +39,7 @@
         implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
 
     private static final String PREFERENCE_KEY = "bluetooth_show_leaudio_device_details";
+    private static final String CONFIG_LE_AUDIO_ENABLED_BY_DEFAULT = "le_audio_enabled_by_default";
     static int sLeAudioSupportedStateCache = BluetoothStatusCodes.ERROR_UNKNOWN;
 
     @VisibleForTesting
@@ -87,8 +88,12 @@
         final boolean leAudioDeviceDetailEnabled = DeviceConfig.getBoolean(
                 DeviceConfig.NAMESPACE_SETTINGS_UI,
                 SettingsUIDeviceConfig.BT_LE_AUDIO_DEVICE_DETAIL_ENABLED, false);
+        final boolean leAudioEnabledByDefault = DeviceConfig.getBoolean(
+                DeviceConfig.NAMESPACE_BLUETOOTH, CONFIG_LE_AUDIO_ENABLED_BY_DEFAULT, false);
 
-        ((SwitchPreference) mPreference).setChecked(leAudioDeviceDetailEnabled);
+        mPreference.setEnabled(!leAudioEnabledByDefault);
+        ((SwitchPreference) mPreference).setChecked(leAudioDeviceDetailEnabled
+                || leAudioEnabledByDefault);
     }
 
     @Override
diff --git a/src/com/android/settings/development/RebootConfirmationDialogFragment.java b/src/com/android/settings/development/RebootConfirmationDialogFragment.java
index 2fa0747..45c3697 100644
--- a/src/com/android/settings/development/RebootConfirmationDialogFragment.java
+++ b/src/com/android/settings/development/RebootConfirmationDialogFragment.java
@@ -28,11 +28,9 @@
 import com.android.settings.R;
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
 
-/**
- * Dialog fragment for reboot confirmation when enabling certain features.
- */
+/** Dialog fragment for reboot confirmation when enabling certain features. */
 public class RebootConfirmationDialogFragment extends InstrumentedDialogFragment
-        implements DialogInterface.OnClickListener {
+        implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
 
     private static final String TAG = "FreeformPrefRebootDlg";
 
@@ -40,18 +38,17 @@
     private final int mCancelButtonId;
     private final RebootConfirmationDialogHost mHost;
 
-    /**
-     * Show an instance of this dialog.
-     */
+    /** Show an instance of this dialog. */
     public static void show(Fragment fragment, int messageId, RebootConfirmationDialogHost host) {
         show(fragment, messageId, R.string.reboot_dialog_reboot_later, host);
     }
 
-    /**
-     * Show an instance of this dialog with cancel button string set as cancelButtonId
-     */
-    public static void show(Fragment fragment, int messageId,
-            int cancelButtonId, RebootConfirmationDialogHost host) {
+    /** Show an instance of this dialog with cancel button string set as cancelButtonId */
+    public static void show(
+            Fragment fragment,
+            int messageId,
+            int cancelButtonId,
+            RebootConfirmationDialogHost host) {
         final FragmentManager manager = fragment.getActivity().getSupportFragmentManager();
         if (manager.findFragmentByTag(TAG) == null) {
             final RebootConfirmationDialogFragment dialog =
@@ -60,8 +57,8 @@
         }
     }
 
-    private RebootConfirmationDialogFragment(int messageId,
-            int cancelButtonId, RebootConfirmationDialogHost host) {
+    private RebootConfirmationDialogFragment(
+            int messageId, int cancelButtonId, RebootConfirmationDialogHost host) {
         mMessageId = messageId;
         mCancelButtonId = cancelButtonId;
         mHost = host;
@@ -89,4 +86,10 @@
             mHost.onRebootCancelled();
         }
     }
+
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        super.onDismiss(dialog);
+        mHost.onRebootDialogDismissed();
+    }
 }
diff --git a/src/com/android/settings/development/RebootConfirmationDialogHost.java b/src/com/android/settings/development/RebootConfirmationDialogHost.java
index 65ffbed..1be25a7 100644
--- a/src/com/android/settings/development/RebootConfirmationDialogHost.java
+++ b/src/com/android/settings/development/RebootConfirmationDialogHost.java
@@ -20,22 +20,20 @@
 import android.content.Intent;
 
 /**
- * Host of {@link RebootConfirmationDialogFragment} that provides callback when user
- * interacts with the UI.
+ * Host of {@link RebootConfirmationDialogFragment} that provides callback when user interacts with
+ * the UI.
  */
 public interface RebootConfirmationDialogHost {
-    /**
-     * Called when user made a decision to reboot the device.
-     */
+    /** Called when user made a decision to reboot the device. */
     default void onRebootConfirmed(Context context) {
         // user presses button "Reboot now", reboot the device
         final Intent intent = new Intent(Intent.ACTION_REBOOT);
         context.startActivity(intent);
     }
 
-    /**
-     * Called when user made a decision to cancel the reboot
-     * Default to do nothing
-     */
+    /** Called when user made a decision to cancel the reboot Default to do nothing */
     default void onRebootCancelled() {}
+
+    /** Called when reboot dialog is dismissed Default to do nothing */
+    default void onRebootDialogDismissed() {}
 }
diff --git a/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverController.java b/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverController.java
index 04252fa..1a065a9 100644
--- a/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverController.java
+++ b/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverController.java
@@ -17,6 +17,7 @@
 package com.android.settings.development.graphicsdriver;
 
 import android.content.Context;
+import android.content.Intent;
 import android.os.GraphicsEnvironment;
 import android.os.SystemProperties;
 import android.text.TextUtils;
@@ -33,9 +34,7 @@
 import com.android.settings.development.RebootConfirmationDialogHost;
 import com.android.settingslib.development.DeveloperOptionsPreferenceController;
 
-/**
- * Controller to handle the events when user toggles this developer option switch: Enable ANGLE
- */
+/** Controller to handle the events when user toggles this developer option switch: Enable ANGLE */
 public class GraphicsDriverEnableAngleAsSystemDriverController
         extends DeveloperOptionsPreferenceController
         implements Preference.OnPreferenceChangeListener,
@@ -50,14 +49,15 @@
 
     private final GraphicsDriverSystemPropertiesWrapper mSystemProperties;
 
+    private boolean mShouldToggleSwitchBackOnRebootDialogDismiss;
+
     @VisibleForTesting
     static final String PROPERTY_RO_GFX_ANGLE_SUPPORTED = "ro.gfx.angle.supported";
 
     @VisibleForTesting
     static final String PROPERTY_PERSISTENT_GRAPHICS_EGL = "persist.graphics.egl";
 
-    @VisibleForTesting
-    static final String ANGLE_DRIVER_SUFFIX = "angle";
+    @VisibleForTesting static final String ANGLE_DRIVER_SUFFIX = "angle";
 
     @VisibleForTesting
     static class Injector {
@@ -87,6 +87,10 @@
         super(context);
         mFragment = fragment;
         mSystemProperties = injector.createSystemPropertiesWrapper();
+        // By default, when the reboot dialog is dismissed we want to toggle the switch back.
+        // Exception is when user chooses to reboot now, the switch should keep its current value
+        // and persist its' state over reboot.
+        mShouldToggleSwitchBackOnRebootDialogDismiss = true;
     }
 
     @Override
@@ -108,11 +112,12 @@
     @VisibleForTesting
     void showRebootDialog() {
         RebootConfirmationDialogFragment.show(
-                mFragment, R.string.reboot_dialog_enable_angle_as_system_driver,
-                R.string.cancel, this);
+                mFragment,
+                R.string.reboot_dialog_enable_angle_as_system_driver,
+                R.string.cancel,
+                this);
     }
 
-
     @Override
     public void updateState(Preference preference) {
         // set switch on if "persist.graphics.egl" is "angle" and angle is built in /vendor
@@ -120,8 +125,9 @@
         final String currentGlesDriver =
                 mSystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL, "");
         final boolean isAngle = TextUtils.equals(ANGLE_DRIVER_SUFFIX, currentGlesDriver);
-        final boolean isAngleSupported = TextUtils
-                .equals(mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true");
+        final boolean isAngleSupported =
+                TextUtils.equals(
+                        mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true");
         ((SwitchPreference) mPreference).setChecked(isAngle && isAngleSupported);
         ((SwitchPreference) mPreference).setEnabled(isAngleSupported);
     }
@@ -130,8 +136,9 @@
     protected void onDeveloperOptionsSwitchEnabled() {
         // only enable the switch if ro.gfx.angle.supported is true
         // we use ro.gfx.angle.supported to indicate if ANGLE libs are installed under /vendor
-        final boolean isAngleSupported = TextUtils
-                .equals(mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true");
+        final boolean isAngleSupported =
+                TextUtils.equals(
+                        mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true");
         ((SwitchPreference) mPreference).setEnabled(isAngleSupported);
     }
 
@@ -145,9 +152,7 @@
         ((SwitchPreference) mPreference).setEnabled(false);
     }
 
-    @Override
-    public void onRebootCancelled() {
-        // if user presses button "Cancel", do not reboot the device, and toggles switch back
+    void toggleSwitchBack() {
         final String currentGlesDriver =
                 mSystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL, "");
         if (TextUtils.equals(ANGLE_DRIVER_SUFFIX, currentGlesDriver)) {
@@ -169,4 +174,40 @@
         // if persist.graphics.egl holds values other than the above two, log error message
         Log.e(TAG, "Invalid persist.graphics.egl property value");
     }
+
+    @VisibleForTesting
+    void rebootDevice(Context context) {
+        final Intent intent = new Intent(Intent.ACTION_REBOOT);
+        context.startActivity(intent);
+    }
+
+    @Override
+    public void onRebootConfirmed(Context context) {
+        // User chooses to reboot now, do not toggle switch back
+        mShouldToggleSwitchBackOnRebootDialogDismiss = false;
+
+        // Reboot the device
+        rebootDevice(context);
+    }
+
+    @Override
+    public void onRebootCancelled() {
+        // User chooses to cancel reboot, toggle switch back
+        mShouldToggleSwitchBackOnRebootDialogDismiss = true;
+    }
+
+    @Override
+    public void onRebootDialogDismissed() {
+        // If reboot dialog is dismissed either from
+        // 1) User clicks cancel
+        // 2) User taps phone screen area outside of reboot dialog
+        // do not reboot the device, and toggles switch back.
+        if (mShouldToggleSwitchBackOnRebootDialogDismiss) {
+            toggleSwitchBack();
+        }
+
+        // Reset the flag so that the default option is to toggle switch back
+        // on reboot dialog dismissed.
+        mShouldToggleSwitchBackOnRebootDialogDismiss = true;
+    }
 }
diff --git a/src/com/android/settings/devicelock/DeviceLockPreferenceController.java b/src/com/android/settings/devicelock/DeviceLockPreferenceController.java
new file mode 100644
index 0000000..4b6fe88
--- /dev/null
+++ b/src/com/android/settings/devicelock/DeviceLockPreferenceController.java
@@ -0,0 +1,59 @@
+/*
+ * 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.devicelock;
+
+import android.content.Context;
+import android.devicelock.DeviceLockManager;
+import android.util.Log;
+
+import androidx.preference.Preference;
+
+import com.android.settings.core.BasePreferenceController;
+
+/**
+ * The PreferenceController that manages the Device Lock entry preference.
+ */
+public final class DeviceLockPreferenceController extends BasePreferenceController {
+
+    private static final String TAG = "DeviceLockPreferenceController";
+
+    private final DeviceLockManager mDeviceLockManager;
+
+    public DeviceLockPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+        mDeviceLockManager = mContext.getSystemService(DeviceLockManager.class);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        // TODO(b/282856378): make this entry searchable
+        return AVAILABLE_UNSEARCHABLE;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        mDeviceLockManager.getKioskApps(mContext.getMainExecutor(),
+                result -> {
+                    // if kiosk apps present on the device, the device is provisioned by Device Lock
+                    boolean isDeviceProvisionedByDeviceLock = result != null && !result.isEmpty();
+                    Log.d(TAG, "Set preference visibility to " + isDeviceProvisionedByDeviceLock);
+                    // TODO(b/282179089): find alternatives instead of calling setVisible
+                    preference.setVisible(isDeviceProvisionedByDeviceLock);
+                });
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/BatteryBackupHelper.java b/src/com/android/settings/fuelgauge/BatteryBackupHelper.java
index eb4bbf6..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,9 +52,19 @@
 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 = ":";
@@ -69,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,33 +102,50 @@
             return;
         }
         final List<String> allowlistedApps = getFullPowerList();
-        if (allowlistedApps != null) {
-            backupOptimizationMode(data, allowlistedApps);
+        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
@@ -220,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(
@@ -299,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);
@@ -308,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/fuelgauge/batterytip/BatteryTipPreferenceController.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
index 214b01a..b041003 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
@@ -18,7 +18,9 @@
 
 import android.annotation.Nullable;
 import android.content.Context;
+import android.os.BadParcelableException;
 import android.os.Bundle;
+import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
@@ -142,14 +144,26 @@
     }
 
     public void restoreInstanceState(Bundle bundle) {
-        if (bundle != null) {
+        if (bundle == null) {
+            return;
+        }
+        try {
             List<BatteryTip> batteryTips = bundle.getParcelableArrayList(KEY_BATTERY_TIPS);
             updateBatteryTips(batteryTips);
+        } catch (BadParcelableException e) {
+            Log.e(TAG, "failed to invoke restoreInstanceState()", e);
         }
     }
 
-    public void saveInstanceState(Bundle outState) {
-        outState.putParcelableList(KEY_BATTERY_TIPS, mBatteryTips);
+    public void saveInstanceState(Bundle bundle) {
+        if (bundle == null) {
+            return;
+        }
+        try {
+            bundle.putParcelableList(KEY_BATTERY_TIPS, mBatteryTips);
+        } catch (BadParcelableException e) {
+            Log.e(TAG, "failed to invoke saveInstanceState()", e);
+        }
     }
 
     public boolean needUpdate() {
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/tests/robotests/src/com/android/settings/devicelock/DeviceLockPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/devicelock/DeviceLockPreferenceControllerTest.java
new file mode 100644
index 0000000..3176969
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/devicelock/DeviceLockPreferenceControllerTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.devicelock;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.devicelock.DeviceLockManager;
+import android.os.OutcomeReceiver;
+
+import androidx.preference.Preference;
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.Collections;
+import java.util.Map;
+
+@RunWith(RobolectricTestRunner.class)
+public final class DeviceLockPreferenceControllerTest {
+
+    private static final String TEST_PREFERENCE_KEY = "KEY";
+    private static final Map<Integer, String> TEST_KIOSK_APPS = Map.of(0, "test");
+    @Mock
+    private DeviceLockManager mDeviceLockManager;
+    @Captor
+    private ArgumentCaptor<OutcomeReceiver<Map<Integer, String>, Exception>>
+            mOutcomeReceiverArgumentCaptor;
+    private DeviceLockPreferenceController mController;
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = ApplicationProvider.getApplicationContext();
+        Context context = spy(mContext);
+        when(context.getSystemService(DeviceLockManager.class)).thenReturn(mDeviceLockManager);
+        mController = new DeviceLockPreferenceController(context, TEST_PREFERENCE_KEY);
+    }
+
+    @Test
+    public void testUpdateState_preferenceBecomesInvisibleIfNoKioskAppsPresent() {
+        Preference preference = new Preference(mContext, null, 0, 0);
+        preference.setVisible(true);
+
+        mController.updateState(preference);
+
+        verify(mDeviceLockManager).getKioskApps(any(), mOutcomeReceiverArgumentCaptor.capture());
+        OutcomeReceiver<Map<Integer, String>, Exception> outcomeReceiver =
+                mOutcomeReceiverArgumentCaptor.getValue();
+
+        outcomeReceiver.onResult(Collections.emptyMap());
+        assertThat(preference.isVisible()).isFalse();
+    }
+
+    @Test
+    public void testUpdateState_preferenceBecomesVisibleIfKioskAppsPresent() {
+        Preference preference = new Preference(mContext, null, 0, 0);
+        preference.setVisible(false);
+
+        mController.updateState(preference);
+
+        verify(mDeviceLockManager).getKioskApps(any(), mOutcomeReceiverArgumentCaptor.capture());
+        OutcomeReceiver<Map<Integer, String>, Exception> outcomeReceiver =
+                mOutcomeReceiverArgumentCaptor.getValue();
+
+        outcomeReceiver.onResult(TEST_KIOSK_APPS);
+        assertThat(preference.isVisible()).isTrue();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
index a800fdb..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
@@ -286,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);
@@ -330,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);
@@ -401,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/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest.java b/tests/unit/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest.java
index 3f85535..c23292a 100644
--- a/tests/unit/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest.java
+++ b/tests/unit/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest.java
@@ -56,11 +56,39 @@
 
     private GraphicsDriverEnableAngleAsSystemDriverController mController;
 
-    @Mock
-    private DevelopmentSettingsDashboardFragment mFragment;
+    // Signal to wait for SystemProperty values changed
+    private class PropertyChangeSignal {
+        private CountDownLatch mCountDownLatch;
 
-    @Mock
-    private GraphicsDriverSystemPropertiesWrapper mSystemPropertiesMock;
+        private Runnable mCountDownJob;
+
+        PropertyChangeSignal() {
+            mCountDownLatch = new CountDownLatch(1);
+            mCountDownJob =
+                    new Runnable() {
+                        @Override
+                        public void run() {
+                            mCountDownLatch.countDown();
+                        }
+                    };
+        }
+
+        public Runnable getCountDownJob() {
+            return mCountDownJob;
+        }
+
+        public void wait(int timeoutInMilliSeconds) {
+            try {
+                mCountDownLatch.await(timeoutInMilliSeconds, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException e) {
+                Assert.fail(e.getMessage());
+            }
+        }
+    }
+
+    @Mock private DevelopmentSettingsDashboardFragment mFragment;
+
+    @Mock private GraphicsDriverSystemPropertiesWrapper mSystemPropertiesMock;
 
     @Before
     public void setUp() {
@@ -76,18 +104,27 @@
         // so we can force the SystemProperties with values we need to run tests.
         // 2) Override the showRebootDialog() to do nothing.
         // We do not need to pop up the reboot dialog in the test.
+        // 3) Override the rebootDevice() to do nothing.
         mController = new GraphicsDriverEnableAngleAsSystemDriverController(
-            mContext, mFragment, new Injector(){
-                @Override
-                public GraphicsDriverSystemPropertiesWrapper createSystemPropertiesWrapper() {
-                    return mSystemPropertiesMock;
-                }
-            }) {
-                @Override
-                void showRebootDialog() {
-                    // do nothing
-                }
-        };
+                mContext,
+                mFragment,
+                new Injector() {
+                    @Override
+                    public GraphicsDriverSystemPropertiesWrapper
+                            createSystemPropertiesWrapper() {
+                            return mSystemPropertiesMock;
+                        }
+                    }) {
+                    @Override
+                    void showRebootDialog() {
+                        // do nothing
+                    }
+
+                    @Override
+                    void rebootDevice(Context context) {
+                        // do nothing
+                    }
+                };
 
         final PreferenceManager preferenceManager = new PreferenceManager(mContext);
         final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
@@ -99,58 +136,42 @@
 
     @Test
     public void onPreferenceChange_switchOn_shouldEnableAngleAsSystemDriver() {
+        // Step 1: toggle the switch "Enable ANGLE" on
         // Add a callback when SystemProperty changes.
         // This allows the thread to wait until
         // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
-        final CountDownLatch countDownLatch = new CountDownLatch(1);
-        Runnable countDown = new Runnable() {
-            @Override
-            public void run() {
-                countDownLatch.countDown();
-            }
-        };
-        SystemProperties.addChangeCallback(countDown);
-
-        // Test onPreferenceChange(true) updates the persist.graphics.egl to "angle"
+        PropertyChangeSignal propertyChangeSignal = new PropertyChangeSignal();
+        SystemProperties.addChangeCallback(propertyChangeSignal.getCountDownJob());
         mController.onPreferenceChange(mPreference, true);
-        try {
-            countDownLatch.await(100, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException e) {
-            Assert.fail(e.getMessage());
-        }
+        propertyChangeSignal.wait(100);
+
+        // Step 2: verify results
         final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
         assertThat(systemEGLDriver).isEqualTo(ANGLE_DRIVER_SUFFIX);
 
+        // Step 3: clean up
         // Done with the test, remove the callback
-        SystemProperties.removeChangeCallback(countDown);
+        SystemProperties.removeChangeCallback(propertyChangeSignal.getCountDownJob());
     }
 
     @Test
     public void onPreferenceChange_switchOff_shouldDisableAngleAsSystemDriver() {
+        // Step 1: toggle the switch "Enable ANGLE" off
         // Add a callback when SystemProperty changes.
         // This allows the thread to wait until
         // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
-        final CountDownLatch countDownLatch = new CountDownLatch(1);
-        Runnable countDown = new Runnable() {
-            @Override
-            public void run() {
-                countDownLatch.countDown();
-            }
-        };
-        SystemProperties.addChangeCallback(countDown);
-
-        // Test onPreferenceChange(false) updates the persist.graphics.egl to ""
+        PropertyChangeSignal propertyChangeSignal = new PropertyChangeSignal();
+        SystemProperties.addChangeCallback(propertyChangeSignal.getCountDownJob());
         mController.onPreferenceChange(mPreference, false);
-        try {
-            countDownLatch.await(100, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException e) {
-            Assert.fail(e.getMessage());
-        }
+        propertyChangeSignal.wait(100);
+
+        // Step 2: verify results
         final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
         assertThat(systemEGLDriver).isEqualTo("");
 
+        // Step 3: clean up
         // Done with the test, remove the callback
-        SystemProperties.removeChangeCallback(countDown);
+        SystemProperties.removeChangeCallback(propertyChangeSignal.getCountDownJob());
     }
 
     @Test
@@ -162,8 +183,7 @@
 
     @Test
     public void updateState_angleNotSupported_PreferenceShouldNotBeChecked() {
-        when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any()))
-                .thenReturn("");
+        when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any())).thenReturn("");
         mController.updateState(mPreference);
         assertThat(mPreference.isChecked()).isFalse();
     }
@@ -191,8 +211,7 @@
             updateState_angleSupported_angleIsNotSystemGLESDriver_PreferenceShouldNotBeChecked() {
         when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any()))
                 .thenReturn("true");
-        when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
-                .thenReturn("");
+        when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any())).thenReturn("");
         mController.updateState(mPreference);
         assertThat(mPreference.isChecked()).isFalse();
     }
@@ -218,28 +237,18 @@
         // Add a callback when SystemProperty changes.
         // This allows the thread to wait until
         // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
-        final CountDownLatch countDownLatch = new CountDownLatch(1);
-        Runnable countDown = new Runnable() {
-            @Override
-            public void run() {
-                countDownLatch.countDown();
-            }
-        };
-        SystemProperties.addChangeCallback(countDown);
+        PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal();
+        SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob());
 
         // Test that onDeveloperOptionSwitchDisabled,
         // persist.graphics.egl updates to ""
         mController.onDeveloperOptionsSwitchDisabled();
-        try {
-            countDownLatch.await(100, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException e) {
-            Assert.fail(e.getMessage());
-        }
+        propertyChangeSignal1.wait(100);
         final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
         assertThat(systemEGLDriver).isEqualTo("");
 
         // Done with the test, remove the callback
-        SystemProperties.removeChangeCallback(countDown);
+        SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob());
     }
 
     @Test
@@ -256,70 +265,217 @@
 
     @Test
     public void onRebootCancelled_ToggleSwitchFromOnToOff() {
+        // Step 1: Toggle the "Enable ANGLE" switch on
         // Add a callback when SystemProperty changes.
         // This allows the thread to wait until
         // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
-        final CountDownLatch countDownLatch = new CountDownLatch(1);
-        Runnable countDown = new Runnable() {
-            @Override
-            public void run() {
-                countDownLatch.countDown();
-            }
-        };
-        SystemProperties.addChangeCallback(countDown);
+        PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal();
+        SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob());
+        mController.onPreferenceChange(mPreference, true);
+        // Block the following code execution until the "persist.graphics.egl" property value is
+        // changed.
+        propertyChangeSignal1.wait(100);
 
-        // Test that if the current persist.graphics.egl is "angle",
-        // when reboot is cancelled, persist.graphics.egl is changed back to "",
-        // and switch is set to unchecked.
+        // Step 2: Cancel reboot
+        PropertyChangeSignal propertyChangeSignal2 = new PropertyChangeSignal();
+        SystemProperties.addChangeCallback(propertyChangeSignal2.getCountDownJob());
         when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
-                .thenReturn(ANGLE_DRIVER_SUFFIX);
+                .thenReturn(SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL));
         mController.onRebootCancelled();
-        try {
-            countDownLatch.await(100, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException e) {
-            Assert.fail(e.getMessage());
-        }
+        mController.onRebootDialogDismissed();
+        // Block the following code execution until the "persist.graphics.egl" property valye is
+        // changed.
+        propertyChangeSignal2.wait(100);
 
+        // Step 3: Verify results
+        // 1) Test that persist.graphics.egl is changed back to "".
         final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
         assertThat(systemEGLDriver).isEqualTo("");
+        // 2) Test that the switch is set to unchecked.
         assertThat(mPreference.isChecked()).isFalse();
 
-        // Done with the test, remove the callback.
-        SystemProperties.removeChangeCallback(countDown);
+        // Step 4: Clean up
+        // Done with the test, remove the callback
+        SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob());
+        SystemProperties.removeChangeCallback(propertyChangeSignal2.getCountDownJob());
     }
 
     @Test
     public void onRebootCancelled_ToggleSwitchFromOffToOn() {
+        // Step 1: Toggle off the switch "Enable ANGLE"
         // Add a callback when SystemProperty changes.
         // This allows the thread to wait until
         // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
-        final CountDownLatch countDownLatch = new CountDownLatch(1);
-        Runnable countDown = new Runnable() {
-            @Override
-            public void run() {
-                countDownLatch.countDown();
-            }
-        };
-        SystemProperties.addChangeCallback(countDown);
+        PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal();
+        SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob());
+        mController.onPreferenceChange(mPreference, false);
+        // Block the following code execution until the "persist.graphics.egl" property value is
+        // changed.
+        propertyChangeSignal1.wait(100);
 
-        // Test that if the current persist.graphics.egl is "",
-        // when reboot is cancelled, persist.graphics.egl is changed back to "angle",
-        // and switch is set to checked.
+        // Step 2: Cancel reboot
+        PropertyChangeSignal propertyChangeSignal2 = new PropertyChangeSignal();
+        SystemProperties.addChangeCallback(propertyChangeSignal2.getCountDownJob());
         when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
-                .thenReturn("");
+                .thenReturn(SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL));
         mController.onRebootCancelled();
-        try {
-            countDownLatch.await(100, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException e) {
-            Assert.fail(e.getMessage());
-        }
+        mController.onRebootDialogDismissed();
+        // Block the following code execution until the "persist.graphics.egl" property valye is
+        // changed.
+        propertyChangeSignal2.wait(100);
 
+        // Step 3: Verify results
+        // 1) Test that persist.graphics.egl is changed back to "ANGLE"
         final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
         assertThat(systemEGLDriver).isEqualTo(ANGLE_DRIVER_SUFFIX);
+        // 2) Test that the switch is set to checked
         assertThat(mPreference.isChecked()).isTrue();
 
+        // Step 4: Clean up
         // Done with the test, remove the callback.
-        SystemProperties.removeChangeCallback(countDown);
+        SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob());
+        SystemProperties.removeChangeCallback(propertyChangeSignal2.getCountDownJob());
     }
 
+    @Test
+    public void onRebootDialogDismissed_ToggleSwitchFromOnToOff() {
+        // Step 1: Toggle on the switch "Enable ANGLE"
+        // Add a callback when SystemProperty changes.
+        // This allows the thread to wait until
+        // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
+        PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal();
+        SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob());
+        mController.onPreferenceChange(mPreference, true);
+        // Block the following code execution until the "persist.graphics.egl" property value is
+        // changed.
+        propertyChangeSignal1.wait(100);
+
+        // Step 2: Dismiss the reboot dialog
+        PropertyChangeSignal propertyChangeSignal2 = new PropertyChangeSignal();
+        SystemProperties.addChangeCallback(propertyChangeSignal2.getCountDownJob());
+        when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
+                .thenReturn(SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL));
+        mController.onRebootDialogDismissed();
+        // Block the following code execution until the "persist.graphics.egl" property valye is
+        // changed.
+        propertyChangeSignal2.wait(100);
+
+        // Step 3: Verify results
+        // 1) Test that persist.graphics.egl is changed back to "".
+        final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
+        assertThat(systemEGLDriver).isEqualTo("");
+        // 2) Test that the switch is set to unchecked.
+        assertThat(mPreference.isChecked()).isFalse();
+
+        // Step 4: Clean up
+        // Done with the test, remove the callback
+        SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob());
+        SystemProperties.removeChangeCallback(propertyChangeSignal2.getCountDownJob());
+    }
+
+    @Test
+    public void onRebootDialogDismissed_ToggleSwitchFromOffToOn() {
+        // Step 1: Toggle on the switch "Enable ANGLE"
+        // Add a callback when SystemProperty changes.
+        // This allows the thread to wait until
+        // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
+        PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal();
+        SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob());
+        mController.onPreferenceChange(mPreference, false);
+        // Block the following code execution until the "persist.graphics.egl" property value is
+        // changed.
+        propertyChangeSignal1.wait(100);
+
+        // Step 2: Dismiss the reboot dialog
+        PropertyChangeSignal propertyChangeSignal2 = new PropertyChangeSignal();
+        SystemProperties.addChangeCallback(propertyChangeSignal2.getCountDownJob());
+        when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
+                .thenReturn(SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL));
+        mController.onRebootDialogDismissed();
+        // Block the following code execution until the "persist.graphics.egl" property valye is
+        // changed.
+        propertyChangeSignal2.wait(100);
+
+        // Step 3: Verify results
+        // 1) Test that persist.graphics.egl is changed back to "ANGLE"
+        final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
+        assertThat(systemEGLDriver).isEqualTo(ANGLE_DRIVER_SUFFIX);
+        // 2) Test that the switch is set to checked
+        assertThat(mPreference.isChecked()).isTrue();
+
+        // Step 4: Clean up
+        // Done with the test, remove the callback
+        SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob());
+        SystemProperties.removeChangeCallback(propertyChangeSignal2.getCountDownJob());
+    }
+
+    @Test
+    public void onRebootDialogConfirmed_ToggleSwitchOnRemainsOn() {
+        // Step 1: Toggle on the switch "Enable ANGLE"
+        // Add a callback when SystemProperty changes.
+        // This allows the thread to wait until
+        // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
+        PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal();
+        SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob());
+        mController.onPreferenceChange(mPreference, true);
+        // Block the following code execution until the "persist.graphics.egl" property value is
+        // changed.
+        propertyChangeSignal1.wait(100);
+
+        // Step 2: Confirm reboot
+        PropertyChangeSignal propertyChangeSignal2 = new PropertyChangeSignal();
+        SystemProperties.addChangeCallback(propertyChangeSignal2.getCountDownJob());
+        when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
+                .thenReturn(SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL));
+        mController.onRebootConfirmed(mContext);
+        mController.onRebootDialogDismissed();
+        // Block the following code execution until the "persist.graphics.egl" property valye is
+        // changed.
+        propertyChangeSignal2.wait(100);
+
+        // Step 3: Verify Results
+        // Test that persist.graphics.egl remains to be "ANGLE"
+        final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
+        assertThat(systemEGLDriver).isEqualTo(ANGLE_DRIVER_SUFFIX);
+
+        // Step 4: Clean up
+        // Done with the test, remove the callback
+        SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob());
+        SystemProperties.removeChangeCallback(propertyChangeSignal2.getCountDownJob());
+    }
+
+    @Test
+    public void onRebootDialogConfirmed_ToggleSwitchOffRemainsOff() {
+        // Step 1: Toggle off the switch "Enable ANGLE"
+        // Add a callback when SystemProperty changes.
+        // This allows the thread to wait until
+        // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
+        PropertyChangeSignal propertyChangeSignal1 = new PropertyChangeSignal();
+        SystemProperties.addChangeCallback(propertyChangeSignal1.getCountDownJob());
+        mController.onPreferenceChange(mPreference, false);
+        // Block the following code execution until the "persist.graphics.egl" property value is
+        // changed.
+        propertyChangeSignal1.wait(100);
+
+        // Step 2: Confirm reboot
+        PropertyChangeSignal propertyChangeSignal2 = new PropertyChangeSignal();
+        SystemProperties.addChangeCallback(propertyChangeSignal2.getCountDownJob());
+        when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
+                .thenReturn(SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL));
+        mController.onRebootConfirmed(mContext);
+        mController.onRebootDialogDismissed();
+        // Block the following code execution until the "persist.graphics.egl" property valye is
+        // changed.
+        propertyChangeSignal2.wait(100);
+
+        // Step 3: Verify Results
+        // Test that persist.graphics.egl remains to be ""
+        final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
+        assertThat(systemEGLDriver).isEqualTo("");
+
+        // Step 4: Clean up
+        // Done with the test, remove the callback
+        SystemProperties.removeChangeCallback(propertyChangeSignal1.getCountDownJob());
+        SystemProperties.removeChangeCallback(propertyChangeSignal2.getCountDownJob());
+    }
 }