Merge "[LE adudio] The condition of right location is wrong."
diff --git a/res/layout/confirm_convert_fbe.xml b/res/layout/confirm_convert_fbe.xml
deleted file mode 100644
index 537c368..0000000
--- a/res/layout/confirm_convert_fbe.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:orientation="vertical"
-            android:layout_marginBottom="12dp" >
-
-        <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginStart="12dp"
-                android:layout_marginEnd="12dp"
-                android:layout_marginTop="12dp"
-                android:textSize="18sp"
-                android:text="@string/confirm_convert_to_fbe_warning" />
-
-        <LinearLayout
-                android:layout_width="wrap_content"
-                android:layout_height="fill_parent"
-                android:layout_gravity="center"
-                android:orientation="horizontal">
-            <Button
-                    android:id="@+id/button_confirm_convert_fbe"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="bottom"
-                    android:layout_marginBottom="12dp"
-                    android:text="@string/button_confirm_convert_fbe" />
-        </LinearLayout>
-
-</LinearLayout>
diff --git a/res/layout/convert_fbe.xml b/res/layout/convert_fbe.xml
deleted file mode 100644
index d1e0cea..0000000
--- a/res/layout/convert_fbe.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:orientation="vertical"
-            android:layout_marginBottom="12dp" >
-
-        <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginStart="@dimen/preference_no_icon_padding_start"
-                android:layout_marginEnd="12dp"
-                android:layout_marginTop="12dp"
-                android:textSize="18sp"
-                android:text="@string/convert_to_fbe_warning" />
-
-        <LinearLayout
-                android:layout_width="wrap_content"
-                android:layout_height="fill_parent"
-                android:layout_gravity="center"
-                android:orientation="horizontal">
-            <Button
-                    android:id="@+id/button_convert_fbe"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="bottom"
-                    android:layout_marginBottom="12dp"
-                    android:text="@string/button_convert_fbe" />
-        </LinearLayout>
-
-</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5042302..8ea6756 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -329,14 +329,16 @@
 
     <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=none] -->
     <string name="bluetooth_disable_a2dp_hw_offload">Disable Bluetooth A2DP hardware offload</string>
-    <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=none] -->
-    <string name="bluetooth_disable_a2dp_hw_offload_dialog_title">Restart Device?</string>
-    <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=none] -->
-    <string name="bluetooth_disable_a2dp_hw_offload_dialog_message">You need to restart your device to change this setting.</string>
-    <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=none] -->
-    <string name="bluetooth_disable_a2dp_hw_offload_dialog_confirm">Restart</string>
-    <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=none] -->
-    <string name="bluetooth_disable_a2dp_hw_offload_dialog_cancel">Cancel</string>
+    <!-- UI debug setting: Disable Bluetooth LE AUDIO hardware offload [CHAR LIMIT=none] -->
+    <string name="bluetooth_disable_le_audio_hw_offload">Disable Bluetooth LE AUDIO hardware offload</string>
+    <!-- UI debug setting: Disable Bluetooth hardware offload [CHAR LIMIT=none] -->
+    <string name="bluetooth_disable_hw_offload_dialog_title">Restart Device?</string>
+    <!-- UI debug setting: Disable Bluetooth hardware offload [CHAR LIMIT=none] -->
+    <string name="bluetooth_disable_hw_offload_dialog_message">You need to restart your device to change this setting.</string>
+    <!-- UI debug setting: Disable Bluetooth hardware offload [CHAR LIMIT=none] -->
+    <string name="bluetooth_disable_hw_offload_dialog_confirm">Restart</string>
+    <!-- UI debug setting: Disable Bluetooth hardware offload [CHAR LIMIT=none] -->
+    <string name="bluetooth_disable_hw_offload_dialog_cancel">Cancel</string>
 
     <!-- Title for Bluetooth device group with media capability group [CHAR LIMIT=none]-->
     <string name="connected_device_media_device_title">Media devices</string>
@@ -11396,11 +11398,6 @@
     <!-- Title for the See more preference item in Special app access settings [CHAR LIMIT=30] -->
     <string name="special_access_more">See more</string>
 
-    <!-- Developer option to convert to file encryption - final warning -->
-    <string name="confirm_convert_to_fbe_warning">Really wipe user data and convert to file encryption?</string>
-    <!-- Developer option to convert to file encryption - final button -->
-    <string name="button_confirm_convert_fbe">Wipe and convert</string>
-
     <!-- Reset rate-limiting in the system service ShortcutManager.  "ShortcutManager" is the name of a system service and not translatable.
     If the word "rate-limit" is hard to translate, use "Reset ShortcutManager API call limit" as the source text, which means
     the same thing in this context.
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index cd37f4c..5868be7 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -88,12 +88,6 @@
             android:summary="@string/runningservices_settings_summary"
             android:fragment="com.android.settings.applications.RunningServices" />
 
-        <Preference
-            android:key="convert_to_file_encryption"
-            android:title="@string/convert_to_file_encryption"
-            android:summary="@string/convert_to_file_encryption_enabled"
-            android:fragment="com.android.settings.applications.ConvertToFbe" />
-
         <com.android.settings.development.ColorModePreference
             android:key="picture_color_mode"
             android:title="@string/picture_color_mode"
@@ -312,6 +306,10 @@
             android:key="bluetooth_disable_a2dp_hw_offload"
             android:title="@string/bluetooth_disable_a2dp_hw_offload" />
 
+        <SwitchPreference
+            android:key="bluetooth_disable_le_audio_hw_offload"
+            android:title="@string/bluetooth_disable_le_audio_hw_offload" />
+
         <ListPreference
             android:key="bluetooth_select_avrcp_version"
             android:title="@string/bluetooth_select_avrcp_version_string"
diff --git a/src/com/android/settings/ResetNetworkConfirm.java b/src/com/android/settings/ResetNetworkConfirm.java
index f79bdb2..eff487b 100644
--- a/src/com/android/settings/ResetNetworkConfirm.java
+++ b/src/com/android/settings/ResetNetworkConfirm.java
@@ -138,7 +138,7 @@
             if (btManager != null) {
                 BluetoothAdapter btAdapter = btManager.getAdapter();
                 if (btAdapter != null) {
-                    btAdapter.factoryReset();
+                    btAdapter.clearBluetooth();
                 }
             }
 
diff --git a/src/com/android/settings/applications/ConfirmConvertToFbe.java b/src/com/android/settings/applications/ConfirmConvertToFbe.java
deleted file mode 100644
index 35ddc6b..0000000
--- a/src/com/android/settings/applications/ConfirmConvertToFbe.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2016 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.applications;
-
-import android.app.settings.SettingsEnums;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-
-import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
-
-public class ConfirmConvertToFbe extends SettingsPreferenceFragment {
-    static final String TAG = "ConfirmConvertToFBE";
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-                Bundle savedInstanceState) {
-        View rootView = inflater.inflate(R.layout.confirm_convert_fbe, null);
-
-        final Button button = (Button) rootView.findViewById(R.id.button_confirm_convert_fbe);
-        button.setOnClickListener(new View.OnClickListener() {
-            public void onClick(View v) {
-                Intent intent = new Intent(Intent.ACTION_FACTORY_RESET);
-                intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-                intent.setPackage("android");
-                intent.putExtra(Intent.EXTRA_REASON, "convert_fbe");
-                getActivity().sendBroadcast(intent);
-            }
-        });
-
-        return rootView;
-    }
-
-    @Override
-    public int getMetricsCategory() {
-        return SettingsEnums.CONVERT_FBE_CONFIRM;
-    }
-}
diff --git a/src/com/android/settings/applications/ConvertToFbe.java b/src/com/android/settings/applications/ConvertToFbe.java
deleted file mode 100644
index d470011..0000000
--- a/src/com/android/settings/applications/ConvertToFbe.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2015 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.applications;
-
-import android.annotation.Nullable;
-import android.app.Activity;
-import android.app.settings.SettingsEnums;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-
-import com.android.settings.R;
-import com.android.settings.core.InstrumentedFragment;
-import com.android.settings.core.SubSettingLauncher;
-import com.android.settings.password.ChooseLockSettingsHelper;
-
-/* Class to prompt for conversion of userdata to file based encryption
- */
-public class ConvertToFbe extends InstrumentedFragment {
-    static final String TAG = "ConvertToFBE";
-    private static final int KEYGUARD_REQUEST = 55;
-
-    private boolean runKeyguardConfirmation(int request) {
-        Resources res = getActivity().getResources();
-        final ChooseLockSettingsHelper.Builder builder =
-                new ChooseLockSettingsHelper.Builder(getActivity(), this);
-        return builder.setRequestCode(request)
-                .setTitle(res.getText(R.string.convert_to_file_encryption))
-                .show();
-    }
-
-    @Override
-    public void onCreate(@Nullable Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        getActivity().setTitle(R.string.convert_to_file_encryption);
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-            Bundle savedInstanceState) {
-        View rootView = inflater.inflate(R.layout.convert_fbe, null);
-
-        final Button button = rootView.findViewById(R.id.button_convert_fbe);
-        button.setOnClickListener(v -> {
-            if (!runKeyguardConfirmation(KEYGUARD_REQUEST)) {
-                convert();
-            }
-        });
-
-        return rootView;
-    }
-
-    @Override
-    public void onActivityResult(int requestCode, int resultCode, Intent data) {
-        super.onActivityResult(requestCode, resultCode, data);
-
-        if (requestCode != KEYGUARD_REQUEST) {
-            return;
-        }
-
-        // If the user entered a valid keyguard credential, start the conversion
-        // process
-        if (resultCode == Activity.RESULT_OK) {
-            convert();
-        }
-    }
-
-    private void convert() {
-        new SubSettingLauncher(getContext())
-                .setDestination(ConfirmConvertToFbe.class.getName())
-                .setTitleRes(R.string.convert_to_file_encryption)
-                .setSourceMetricsCategory(getMetricsCategory())
-                .launch();
-    }
-
-    @Override
-    public int getMetricsCategory() {
-        return SettingsEnums.CONVERT_FBE;
-    }
-}
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
index aacf41f..b57ea92 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
@@ -16,10 +16,12 @@
 
 package com.android.settings.bluetooth;
 
+import android.bluetooth.BluetoothCsipSetCoordinator;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.text.TextUtils;
+import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
@@ -31,6 +33,7 @@
 import com.android.settings.R;
 import com.android.settingslib.bluetooth.A2dpProfile;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.LeAudioProfile;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfile;
 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
@@ -39,7 +42,10 @@
 import com.android.settingslib.bluetooth.PbapServerProfile;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * This class adds switches for toggling the individual profiles that a Bluetooth device
@@ -48,8 +54,11 @@
 public class BluetoothDetailsProfilesController extends BluetoothDetailsController
         implements Preference.OnPreferenceClickListener,
         LocalBluetoothProfileManager.ServiceListener {
+    private static final String TAG = "BtDetailsProfilesCtrl";
+
     private static final String KEY_PROFILES_GROUP = "bluetooth_profiles";
     private static final String KEY_BOTTOM_PREFERENCE = "bottom_preference";
+    private static final String HEADSET_CLIENT = "HEADSET_CLIENT";
     private static final int ORDINAL = 99;
 
     @VisibleForTesting
@@ -58,6 +67,9 @@
     private LocalBluetoothManager mManager;
     private LocalBluetoothProfileManager mProfileManager;
     private CachedBluetoothDevice mCachedDevice;
+    private List<CachedBluetoothDevice> mAllOfCachedDevices;
+    private Map<String, List<CachedBluetoothDevice>> mProfileDeviceMap =
+            new HashMap<String, List<CachedBluetoothDevice>>();
 
     @VisibleForTesting
     PreferenceCategory mProfilesContainer;
@@ -68,6 +80,7 @@
         mManager = manager;
         mProfileManager = mManager.getProfileManager();
         mCachedDevice = device;
+        mAllOfCachedDevices = getAllOfCachedBluetoothDevices();
         lifecycle.addObserver(this);
     }
 
@@ -100,11 +113,66 @@
 
     /**
      * Refreshes the state for an existing SwitchPreference for a profile.
+     * If the LeAudio profile is enabled on the LeAudio devices, then the SwitchPreferences of
+     * A2dp profile and Hfp profile are graied out.
      */
     private void refreshProfilePreference(SwitchPreference profilePref,
             LocalBluetoothProfile profile) {
         BluetoothDevice device = mCachedDevice.getDevice();
-        profilePref.setEnabled(!mCachedDevice.isBusy());
+        boolean isLeAudioEnabled = false;
+        if (profile instanceof A2dpProfile || HEADSET_CLIENT.equals(profile.toString())) {
+            LocalBluetoothProfile leAudio = mProfileManager.getLeAudioProfile();
+            if (leAudio != null) {
+                List<CachedBluetoothDevice> leAudioDeviceList = mProfileDeviceMap.get(
+                        leAudio.toString());
+                if (leAudioDeviceList != null
+                        && leAudioDeviceList.stream()
+                        .anyMatch(item -> leAudio.isEnabled(item.getDevice()))) {
+                    isLeAudioEnabled = true;
+                }
+            }
+            if (isLeAudioEnabled) {
+                // If the LeAudio profile is enabled on the LeAudio devices, then the
+                // SwitchPreferences of A2dp profile and Hfp profile are graied out.
+                profilePref.setEnabled(false);
+            } else {
+                List<CachedBluetoothDevice> deviceList = mProfileDeviceMap.get(
+                        profile.toString());
+                boolean isBusy = deviceList != null
+                        && deviceList.stream().anyMatch(item -> item.isBusy());
+                profilePref.setEnabled(!isBusy);
+            }
+        } else if (profile instanceof LeAudioProfile) {
+            List<CachedBluetoothDevice> leAudioDeviceList = mProfileDeviceMap.get(
+                    profile.toString());
+            boolean isLeAudioProfileEnable =
+                    leAudioDeviceList != null && leAudioDeviceList.stream().anyMatch(
+                            item -> profile.isEnabled(item.getDevice()));
+            boolean isBusy = leAudioDeviceList != null
+                    && leAudioDeviceList.stream().anyMatch(item -> item.isBusy());
+            if (isLeAudioProfileEnable && !isBusy) {
+                LocalBluetoothProfile a2dp = mProfileManager.getA2dpProfile();
+                LocalBluetoothProfile hfp = mProfileManager.getHfpClientProfile();
+                // If the LeAudio profile is enabled on the LeAudio devices, then the
+                // SwitchPreferences of A2dp profile and Hfp profile are graied out.
+                if (a2dp != null) {
+                    SwitchPreference pref = mProfilesContainer.findPreference(a2dp.toString());
+                    if (pref != null) {
+                        pref.setEnabled(false);
+                    }
+                }
+                if (hfp != null) {
+                    SwitchPreference pref = mProfilesContainer.findPreference(hfp.toString());
+                    if (pref != null) {
+                        pref.setEnabled(false);
+                    }
+                }
+            }
+            profilePref.setEnabled(!isBusy);
+        } else {
+            profilePref.setEnabled(!mCachedDevice.isBusy());
+        }
+
         if (profile instanceof MapProfile) {
             profilePref.setChecked(device.getMessageAccessPermission()
                     == BluetoothDevice.ACCESS_ALLOWED);
@@ -127,7 +195,7 @@
                     highQualityPref.setVisible(true);
                     highQualityPref.setTitle(a2dp.getHighQualityAudioOptionLabel(device));
                     highQualityPref.setChecked(a2dp.isHighQualityAudioEnabled(device));
-                    highQualityPref.setEnabled(!mCachedDevice.isBusy());
+                    highQualityPref.setEnabled(!mCachedDevice.isBusy() && !isLeAudioEnabled);
                 } else {
                     highQualityPref.setVisible(false);
                 }
@@ -148,6 +216,12 @@
         if (profile instanceof MapProfile) {
             bluetoothDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_ALLOWED);
         }
+
+        if (profile instanceof LeAudioProfile) {
+            enableLeAudioProfile(profile);
+            return;
+        }
+
         profile.setEnabled(bluetoothDevice, true);
     }
 
@@ -155,8 +229,14 @@
      * Helper method to disable a profile for a device
      */
     private void disableProfile(LocalBluetoothProfile profile) {
+        if (profile instanceof LeAudioProfile) {
+            disableLeAudioProfile(profile);
+            return;
+        }
+
         final BluetoothDevice bluetoothDevice = mCachedDevice.getDevice();
         profile.setEnabled(bluetoothDevice, false);
+
         if (profile instanceof MapProfile) {
             bluetoothDevice.setMessageAccessPermission(BluetoothDevice.ACCESS_REJECTED);
         } else if (profile instanceof PbapServerProfile) {
@@ -190,14 +270,33 @@
         return true;
     }
 
-
     /**
      * Helper to get the list of connectable and special profiles.
      */
     private List<LocalBluetoothProfile> getProfiles() {
-        List<LocalBluetoothProfile> result = mCachedDevice.getConnectableProfiles();
-        final BluetoothDevice device = mCachedDevice.getDevice();
+        List<LocalBluetoothProfile> result = new ArrayList<LocalBluetoothProfile>();
+        mProfileDeviceMap.clear();
+        if (mAllOfCachedDevices == null || mAllOfCachedDevices.isEmpty()) {
+            return result;
+        }
+        for (CachedBluetoothDevice cachedItem : mAllOfCachedDevices) {
+            List<LocalBluetoothProfile> tmpResult = cachedItem.getConnectableProfiles();
+            for (LocalBluetoothProfile profile : tmpResult) {
+                if (mProfileDeviceMap.containsKey(profile.toString())) {
+                    mProfileDeviceMap.get(profile.toString()).add(cachedItem);
+                    Log.d(TAG, "getProfiles: " + profile.toString() + " add device "
+                            + cachedItem.getDevice().getAnonymizedAddress());
+                } else {
+                    List<CachedBluetoothDevice> tmpCachedDeviceList =
+                            new ArrayList<CachedBluetoothDevice>();
+                    tmpCachedDeviceList.add(cachedItem);
+                    mProfileDeviceMap.put(profile.toString(), tmpCachedDeviceList);
+                    result.add(profile);
+                }
+            }
+        }
 
+        final BluetoothDevice device = mCachedDevice.getDevice();
         final int pbapPermission = device.getPhonebookAccessPermission();
         // Only provide PBAP cabability if the client device has requested PBAP.
         if (pbapPermission != BluetoothDevice.ACCESS_UNKNOWN) {
@@ -210,10 +309,93 @@
         if (mapPermission != BluetoothDevice.ACCESS_UNKNOWN) {
             result.add(mapProfile);
         }
-
+        Log.d(TAG, "getProfiles:result:" + result);
         return result;
     }
 
+    private List<CachedBluetoothDevice> getAllOfCachedBluetoothDevices() {
+        List<CachedBluetoothDevice> cachedBluetoothDevices = new ArrayList<>();
+        if (mCachedDevice == null) {
+            return cachedBluetoothDevices;
+        }
+        cachedBluetoothDevices.add(mCachedDevice);
+        if (mCachedDevice.getGroupId() != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) {
+            for (CachedBluetoothDevice member : mCachedDevice.getMemberDevice()) {
+                cachedBluetoothDevices.add(member);
+            }
+        }
+        return cachedBluetoothDevices;
+    }
+
+    /**
+     * When user disable the Le Audio profile, the system needs to do two things.
+     * 1) Disable the Le Audio profile for each of the Le Audio devices.
+     * 2) Enable the A2dp profile and Hfp profile for the associated device. The system can't
+     * enable the A2dp profile and Hfp profile if the Le Audio profile is enabled.
+     *
+     * @param profile the LeAudio profile
+     */
+    private void disableLeAudioProfile(LocalBluetoothProfile profile) {
+        if (profile == null || mProfileDeviceMap.get(profile.toString()) == null) {
+            Log.e(TAG, "There is no the LE profile or no device in mProfileDeviceMap. Do nothing.");
+            return;
+        }
+        for (CachedBluetoothDevice leAudioDevice : mProfileDeviceMap.get(profile.toString())) {
+            profile.setEnabled(leAudioDevice.getDevice(), false);
+        }
+
+        LocalBluetoothProfile a2dp = mProfileManager.getA2dpProfile();
+        LocalBluetoothProfile hfp = mProfileManager.getHfpClientProfile();
+        if (a2dp != null && mProfileDeviceMap.get(a2dp.toString()) != null) {
+            for (CachedBluetoothDevice a2dpDevice : mProfileDeviceMap.get(a2dp.toString())) {
+                if (!a2dp.isEnabled(a2dpDevice.getDevice())) {
+                    a2dp.setEnabled(a2dpDevice.getDevice(), true);
+                }
+            }
+        }
+        if (hfp != null && mProfileDeviceMap.get(hfp.toString()) != null) {
+            for (CachedBluetoothDevice hfpDevice : mProfileDeviceMap.get(hfp.toString())) {
+                if (!hfp.isEnabled(hfpDevice.getDevice())) {
+                    hfp.setEnabled(hfpDevice.getDevice(), true);
+                }
+            }
+        }
+    }
+
+    /**
+     * When user enable the Le Audio profile, the system needs to do two things.
+     * 1) Disable the A2dp profile and Hfp profile for the associated device. The system can't
+     * enable the Le Audio if the A2dp profile and Hfp profile are enabled.
+     * 2) Enable the Le Audio profile for each of the Le Audio devices.
+     *
+     * @param profile the LeAudio profile
+     */
+    private void enableLeAudioProfile(LocalBluetoothProfile profile) {
+        if (profile == null || mProfileDeviceMap.get(profile.toString()) == null) {
+            Log.e(TAG, "There is no the LE profile or no device in mProfileDeviceMap. Do nothing.");
+            return;
+        }
+        LocalBluetoothProfile a2dp = mProfileManager.getA2dpProfile();
+        LocalBluetoothProfile hfp = mProfileManager.getHfpClientProfile();
+        if (a2dp != null && mProfileDeviceMap.get(a2dp.toString()) != null) {
+            for (CachedBluetoothDevice a2dpDevice : mProfileDeviceMap.get(a2dp.toString())) {
+                if (a2dp.isEnabled(a2dpDevice.getDevice())) {
+                    a2dp.setEnabled(a2dpDevice.getDevice(), false);
+                }
+            }
+        }
+        if (hfp != null && mProfileDeviceMap.get(hfp.toString()) != null) {
+            for (CachedBluetoothDevice hfpDevice : mProfileDeviceMap.get(hfp.toString())) {
+                if (hfp.isEnabled(hfpDevice.getDevice())) {
+                    hfp.setEnabled(hfpDevice.getDevice(), false);
+                }
+            }
+        }
+        for (CachedBluetoothDevice leAudioDevice : mProfileDeviceMap.get(profile.toString())) {
+            profile.setEnabled(leAudioDevice.getDevice(), true);
+        }
+    }
+
     /**
      * This is a helper method to be called after adding a Preference for a profile. If that
      * profile happened to be A2dp and the device supports high quality audio, it will add a
@@ -243,17 +425,34 @@
 
     @Override
     public void onPause() {
-        super.onPause();
+        for (CachedBluetoothDevice item : mAllOfCachedDevices) {
+            item.unregisterCallback(this);
+        }
         mProfileManager.removeServiceListener(this);
     }
 
     @Override
     public void onResume() {
-        super.onResume();
+        for (CachedBluetoothDevice item : mAllOfCachedDevices) {
+            item.registerCallback(this);
+        }
         mProfileManager.addServiceListener(this);
     }
 
     @Override
+    public void onDeviceAttributesChanged() {
+        for (CachedBluetoothDevice item : mAllOfCachedDevices) {
+            item.unregisterCallback(this);
+        }
+        mAllOfCachedDevices = getAllOfCachedBluetoothDevices();
+        for (CachedBluetoothDevice item : mAllOfCachedDevices) {
+            item.registerCallback(this);
+        }
+
+        super.onDeviceAttributesChanged();
+    }
+
+    @Override
     public void onServiceConnected() {
         refresh();
     }
diff --git a/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java b/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java
index 95e663b..2ffa11b 100644
--- a/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java
+++ b/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java
@@ -16,9 +16,12 @@
 
 package com.android.settings.development;
 
+import static com.android.settings.development.BluetoothLeAudioHwOffloadPreferenceController.LE_AUDIO_OFFLOAD_DISABLED_PROPERTY;
+
 import android.content.Context;
 import android.os.SystemProperties;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.SwitchPreference;
 
@@ -34,6 +37,9 @@
     static final String A2DP_OFFLOAD_DISABLED_PROPERTY = "persist.bluetooth.a2dp_offload.disabled";
     static final String A2DP_OFFLOAD_SUPPORTED_PROPERTY = "ro.bluetooth.a2dp_offload.supported";
 
+    @VisibleForTesting
+    boolean mChanged = false;
+
     public BluetoothA2dpHwOffloadPreferenceController(Context context,
             DevelopmentSettingsDashboardFragment fragment) {
         super(context);
@@ -47,7 +53,8 @@
 
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
-        BluetoothA2dpHwOffloadRebootDialog.show(mFragment, this);
+        BluetoothHwOffloadRebootDialog.show(mFragment);
+        mChanged = true;
         return false;
     }
 
@@ -85,10 +92,26 @@
         return offloadSupported ? !offloadDisabled : true;
     }
 
-    public void onA2dpHwDialogConfirmed() {
+    /**
+     * Called when the HwOffloadDialog confirm is clicked.
+     */
+    public void onHwOffloadDialogConfirmed() {
+        if (!mChanged) {
+            return;
+        }
         final boolean offloadDisabled =
                 SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false);
         SystemProperties.set(A2DP_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(!offloadDisabled));
+        if (offloadDisabled) {
+            SystemProperties.set(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY,
+                    Boolean.toString(!offloadDisabled));
+        }
     }
 
+    /**
+     * Called when the HwOffloadDialog cancel is clicked.
+     */
+    public void onHwOffloadDialogCanceled() {
+        mChanged = false;
+    }
 }
diff --git a/src/com/android/settings/development/BluetoothA2dpHwOffloadRebootDialog.java b/src/com/android/settings/development/BluetoothHwOffloadRebootDialog.java
similarity index 60%
rename from src/com/android/settings/development/BluetoothA2dpHwOffloadRebootDialog.java
rename to src/com/android/settings/development/BluetoothHwOffloadRebootDialog.java
index 95ef019..389103e 100644
--- a/src/com/android/settings/development/BluetoothA2dpHwOffloadRebootDialog.java
+++ b/src/com/android/settings/development/BluetoothHwOffloadRebootDialog.java
@@ -28,17 +28,23 @@
 import com.android.settings.R;
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
 
-public class BluetoothA2dpHwOffloadRebootDialog extends InstrumentedDialogFragment
+/**
+ * The a2dp and LE audio offload switch should reboot the device to take effect, the dialog is
+ * to ask the user to reboot the device after a2dp or LE audio offload user preference changed
+ */
+public class BluetoothHwOffloadRebootDialog extends InstrumentedDialogFragment
         implements DialogInterface.OnClickListener {
 
-    public static final String TAG = "BluetoothA2dpHwOffloadReboot";
+    public static final String TAG = "BluetoothHwOffloadReboot";
 
-    public static void show(DevelopmentSettingsDashboardFragment host,
-            BluetoothA2dpHwOffloadPreferenceController controller) {
+    /**
+     * The function to show the HwOffloadReboot Dialog.
+     */
+    public static void show(DevelopmentSettingsDashboardFragment host) {
         final FragmentManager manager = host.getActivity().getSupportFragmentManager();
         if (manager.findFragmentByTag(TAG) == null) {
-            final BluetoothA2dpHwOffloadRebootDialog dialog =
-                    new BluetoothA2dpHwOffloadRebootDialog();
+            final BluetoothHwOffloadRebootDialog dialog =
+                    new BluetoothHwOffloadRebootDialog();
             dialog.setTargetFragment(host, 0 /* requestCode */);
             dialog.show(manager, TAG);
         }
@@ -52,33 +58,44 @@
     @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
         return new AlertDialog.Builder(getActivity())
-                .setMessage(R.string.bluetooth_disable_a2dp_hw_offload_dialog_message)
-                .setTitle(R.string.bluetooth_disable_a2dp_hw_offload_dialog_title)
+                .setMessage(R.string.bluetooth_disable_hw_offload_dialog_message)
+                .setTitle(R.string.bluetooth_disable_hw_offload_dialog_title)
                 .setPositiveButton(
-                        R.string.bluetooth_disable_a2dp_hw_offload_dialog_confirm, this)
+                        R.string.bluetooth_disable_hw_offload_dialog_confirm, this)
                 .setNegativeButton(
-                        R.string.bluetooth_disable_a2dp_hw_offload_dialog_cancel, this)
+                        R.string.bluetooth_disable_hw_offload_dialog_cancel, this)
                 .create();
     }
 
     @Override
     public void onClick(DialogInterface dialog, int which) {
-        final OnA2dpHwDialogConfirmedListener host =
-                (OnA2dpHwDialogConfirmedListener) getTargetFragment();
+        final OnHwOffloadDialogListener host =
+                (OnHwOffloadDialogListener) getTargetFragment();
         if (host == null) {
             return;
         }
         if (which == DialogInterface.BUTTON_POSITIVE) {
-            host.onA2dpHwDialogConfirmed();
+            host.onHwOffloadDialogConfirmed();
             PowerManager pm = getContext().getSystemService(PowerManager.class);
             pm.reboot(null);
+        } else {
+            host.onHwOffloadDialogCanceled();
         }
     }
 
-    public interface OnA2dpHwDialogConfirmedListener {
+    /**
+     * The interface for the HsOffloadDialogListener to provide the action as the
+     * confirmed or canceled clicked.
+     */
+    public interface OnHwOffloadDialogListener {
         /**
          * Called when the user presses reboot on the warning dialog.
          */
-        void onA2dpHwDialogConfirmed();
+        void onHwOffloadDialogConfirmed();
+
+        /**
+         * Called when the user presses cancel on the warning dialog.
+         */
+        void onHwOffloadDialogCanceled();
     }
 }
diff --git a/src/com/android/settings/development/BluetoothLeAudioHwOffloadPreferenceController.java b/src/com/android/settings/development/BluetoothLeAudioHwOffloadPreferenceController.java
new file mode 100644
index 0000000..911b62d
--- /dev/null
+++ b/src/com/android/settings/development/BluetoothLeAudioHwOffloadPreferenceController.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import static com.android.settings.development.BluetoothA2dpHwOffloadPreferenceController.A2DP_OFFLOAD_SUPPORTED_PROPERTY;
+
+import android.content.Context;
+import android.os.SystemProperties;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.SwitchPreference;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+/**
+ * Preference controller to control Bluetooth LE audio offload
+ */
+public class BluetoothLeAudioHwOffloadPreferenceController
+        extends DeveloperOptionsPreferenceController
+        implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
+
+    private static final String PREFERENCE_KEY = "bluetooth_disable_le_audio_hw_offload";
+    private final DevelopmentSettingsDashboardFragment mFragment;
+
+    static final String LE_AUDIO_OFFLOAD_DISABLED_PROPERTY =
+            "persist.bluetooth.leaudio_offload.disabled";
+    static final String LE_AUDIO_OFFLOAD_SUPPORTED_PROPERTY =
+            "ro.bluetooth.leaudio_offload.supported";
+
+    @VisibleForTesting
+    boolean mChanged = false;
+
+    public BluetoothLeAudioHwOffloadPreferenceController(Context context,
+            DevelopmentSettingsDashboardFragment fragment) {
+        super(context);
+        mFragment = fragment;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return PREFERENCE_KEY;
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        BluetoothHwOffloadRebootDialog.show(mFragment);
+        mChanged = true;
+        return false;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        final boolean offloadSupported =
+                SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false)
+                && SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_SUPPORTED_PROPERTY, false);
+        if (offloadSupported) {
+            final boolean offloadDisabled =
+                    SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, true);
+            ((SwitchPreference) mPreference).setChecked(offloadDisabled);
+        } else {
+            mPreference.setEnabled(false);
+            ((SwitchPreference) mPreference).setChecked(true);
+        }
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchDisabled() {
+        super.onDeveloperOptionsSwitchDisabled();
+        final boolean offloadSupported =
+                SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false)
+                && SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_SUPPORTED_PROPERTY, false);
+        if (offloadSupported) {
+            ((SwitchPreference) mPreference).setChecked(true);
+            SystemProperties.set(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, "true");
+        }
+    }
+
+    /**
+     * Check if the le audio offload setting is default value.
+     */
+    public boolean isDefaultValue() {
+        final boolean offloadSupported =
+                SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false)
+                && SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_SUPPORTED_PROPERTY, false);
+        final boolean offloadDisabled =
+                    SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, false);
+        return offloadSupported ? offloadDisabled : true;
+    }
+
+    /**
+     * Called when the HwOffloadDialog confirm is clicked.
+     */
+    public void onHwOffloadDialogConfirmed() {
+        if (!mChanged) {
+            return;
+        }
+
+        final boolean offloadDisabled =
+                SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY,
+                false);
+        SystemProperties.set(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY,
+                Boolean.toString(!offloadDisabled));
+    }
+
+    /**
+     * Called when the HwOffloadDialog cancel is clicked.
+     */
+    public void onHwOffloadDialogCanceled() {
+        mChanged = false;
+    }
+}
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 7556d23..766aa8b 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -79,7 +79,7 @@
 public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFragment
         implements OnMainSwitchChangeListener, OemUnlockDialogHost, AdbDialogHost,
         AdbClearKeysDialogHost, LogPersistDialogHost,
-        BluetoothA2dpHwOffloadRebootDialog.OnA2dpHwDialogConfirmedListener,
+        BluetoothHwOffloadRebootDialog.OnHwOffloadDialogListener,
         AbstractBluetoothPreferenceController.Callback {
 
     private static final String TAG = "DevSettingsDashboard";
@@ -287,12 +287,16 @@
             if (isChecked) {
                 EnableDevelopmentSettingWarningDialog.show(this /* host */);
             } else {
-                final BluetoothA2dpHwOffloadPreferenceController controller =
+                final BluetoothA2dpHwOffloadPreferenceController a2dpController =
                         getDevelopmentOptionsController(
                                 BluetoothA2dpHwOffloadPreferenceController.class);
-                // If A2DP hardware offload isn't default value, we must reboot after disable
+                final BluetoothLeAudioHwOffloadPreferenceController leAudioController =
+                        getDevelopmentOptionsController(
+                                BluetoothLeAudioHwOffloadPreferenceController.class);
+                // If hardware offload isn't default value, we must reboot after disable
                 // developer options. Show a dialog for the user to confirm.
-                if (controller == null || controller.isDefaultValue()) {
+                if ((a2dpController == null || a2dpController.isDefaultValue())
+                        && (leAudioController == null || leAudioController.isDefaultValue())) {
                     disableDeveloperOptions();
                 } else {
                     DisableDevSettingsDialogFragment.show(this /* host */);
@@ -352,10 +356,27 @@
     }
 
     @Override
-    public void onA2dpHwDialogConfirmed() {
-        final BluetoothA2dpHwOffloadPreferenceController controller =
+    public void onHwOffloadDialogConfirmed() {
+        final BluetoothA2dpHwOffloadPreferenceController a2dpController =
                 getDevelopmentOptionsController(BluetoothA2dpHwOffloadPreferenceController.class);
-        controller.onA2dpHwDialogConfirmed();
+        a2dpController.onHwOffloadDialogConfirmed();
+
+        final BluetoothLeAudioHwOffloadPreferenceController leAudioController =
+                getDevelopmentOptionsController(
+                    BluetoothLeAudioHwOffloadPreferenceController.class);
+        leAudioController.onHwOffloadDialogConfirmed();
+    }
+
+    @Override
+    public void onHwOffloadDialogCanceled() {
+        final BluetoothA2dpHwOffloadPreferenceController a2dpController =
+                getDevelopmentOptionsController(BluetoothA2dpHwOffloadPreferenceController.class);
+        a2dpController.onHwOffloadDialogCanceled();
+
+        final BluetoothLeAudioHwOffloadPreferenceController leAudioController =
+                getDevelopmentOptionsController(
+                    BluetoothLeAudioHwOffloadPreferenceController.class);
+        leAudioController.onHwOffloadDialogCanceled();
     }
 
     @Override
@@ -477,7 +498,6 @@
         controllers.add(new HdcpCheckingPreferenceController(context));
         controllers.add(new BluetoothSnoopLogPreferenceController(context));
         controllers.add(new OemUnlockPreferenceController(context, activity, fragment));
-        controllers.add(new FileEncryptionPreferenceController(context));
         controllers.add(new PictureColorModePreferenceController(context, lifecycle));
         controllers.add(new WebViewAppPreferenceController(context));
         controllers.add(new CoolColorTemperaturePreferenceController(context));
@@ -513,6 +533,7 @@
         controllers.add(new BluetoothAvrcpVersionPreferenceController(context));
         controllers.add(new BluetoothMapVersionPreferenceController(context));
         controllers.add(new BluetoothA2dpHwOffloadPreferenceController(context, fragment));
+        controllers.add(new BluetoothLeAudioHwOffloadPreferenceController(context, fragment));
         controllers.add(new BluetoothMaxConnectedAudioDevicesPreferenceController(context));
         controllers.add(new NfcStackDebugLogPreferenceController(context));
         controllers.add(new ShowTapsPreferenceController(context));
diff --git a/src/com/android/settings/development/DisableDevSettingsDialogFragment.java b/src/com/android/settings/development/DisableDevSettingsDialogFragment.java
index 803030e..5db2ed4 100644
--- a/src/com/android/settings/development/DisableDevSettingsDialogFragment.java
+++ b/src/com/android/settings/development/DisableDevSettingsDialogFragment.java
@@ -56,15 +56,15 @@
 
     @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
-        // Reuse the same text of disable_a2dp_hw_offload_dialog.
+        // Reuse the same text of disable_hw_offload_dialog.
         // The text is generic enough to be used for turning off Dev options.
         return new AlertDialog.Builder(getActivity())
-                .setMessage(R.string.bluetooth_disable_a2dp_hw_offload_dialog_message)
-                .setTitle(R.string.bluetooth_disable_a2dp_hw_offload_dialog_title)
+                .setMessage(R.string.bluetooth_disable_hw_offload_dialog_message)
+                .setTitle(R.string.bluetooth_disable_hw_offload_dialog_title)
                 .setPositiveButton(
-                        R.string.bluetooth_disable_a2dp_hw_offload_dialog_confirm, this)
+                        R.string.bluetooth_disable_hw_offload_dialog_confirm, this)
                 .setNegativeButton(
-                        R.string.bluetooth_disable_a2dp_hw_offload_dialog_cancel, this)
+                        R.string.bluetooth_disable_hw_offload_dialog_cancel, this)
                 .create();
     }
 
diff --git a/src/com/android/settings/development/FileEncryptionPreferenceController.java b/src/com/android/settings/development/FileEncryptionPreferenceController.java
deleted file mode 100644
index 82a58ba..0000000
--- a/src/com/android/settings/development/FileEncryptionPreferenceController.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.development;
-
-import android.content.Context;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.storage.IStorageManager;
-import android.text.TextUtils;
-import android.sysprop.CryptoProperties;
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-
-import com.android.settings.R;
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.development.DeveloperOptionsPreferenceController;
-
-public class FileEncryptionPreferenceController extends DeveloperOptionsPreferenceController
-        implements PreferenceControllerMixin {
-
-    private static final String KEY_CONVERT_FBE = "convert_to_file_encryption";
-    private static final String KEY_STORAGE_MANAGER = "mount";
-
-    private final IStorageManager mStorageManager;
-
-    public FileEncryptionPreferenceController(Context context) {
-        super(context);
-
-        mStorageManager = getStorageManager();
-    }
-
-    @Override
-    public boolean isAvailable() {
-        if (mStorageManager == null) {
-            return false;
-        }
-
-        try {
-            return mStorageManager.isConvertibleToFBE();
-        } catch (RemoteException e) {
-            return false;
-        }
-    }
-
-    @Override
-    public String getPreferenceKey() {
-        return KEY_CONVERT_FBE;
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        if (CryptoProperties.type().orElse(CryptoProperties.type_values.NONE) !=
-            CryptoProperties.type_values.FILE) {
-            return;
-        }
-
-        mPreference.setEnabled(false);
-        mPreference.setSummary(
-                mContext.getResources().getString(R.string.convert_to_file_encryption_done));
-    }
-
-    private IStorageManager getStorageManager() {
-        try {
-            return IStorageManager.Stub.asInterface(
-                    ServiceManager.getService(KEY_STORAGE_MANAGER));
-        } catch (VerifyError e) {
-            // Used for tests since Robolectric cannot initialize this class.
-            return null;
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/settings/localepicker/OWNERS b/src/com/android/settings/localepicker/OWNERS
new file mode 100644
index 0000000..12ab32f
--- /dev/null
+++ b/src/com/android/settings/localepicker/OWNERS
@@ -0,0 +1,7 @@
+allenwtsu@google.com

+calvinpan@google.com

+danielwbhuang@google.com

+goldmanj@google.com

+jamescflin@google.com

+joshhou@google.com

+tomhsu@google.com
\ No newline at end of file
diff --git a/src/com/android/settings/network/apn/ApnEditor.java b/src/com/android/settings/network/apn/ApnEditor.java
index 03db1b8..926c77e 100644
--- a/src/com/android/settings/network/apn/ApnEditor.java
+++ b/src/com/android/settings/network/apn/ApnEditor.java
@@ -149,6 +149,7 @@
     private String[] mReadOnlyApnFields;
     private boolean mReadOnlyApn;
     private Uri mCarrierUri;
+    private boolean mIsCarrierIdApn;
 
     /**
      * APN types for data connections.  These are usage categories for an APN
@@ -227,7 +228,8 @@
             Telephony.Carriers.MVNO_TYPE,   // 21
             Telephony.Carriers.MVNO_MATCH_DATA,  // 22
             Telephony.Carriers.EDITED_STATUS,   // 23
-            Telephony.Carriers.USER_EDITABLE    //24
+            Telephony.Carriers.USER_EDITABLE,   // 24
+            Telephony.Carriers.CARRIER_ID       // 25
     };
 
     private static final int ID_INDEX = 0;
@@ -262,6 +264,7 @@
     private static final int MVNO_MATCH_DATA_INDEX = 22;
     private static final int EDITED_INDEX = 23;
     private static final int USER_EDITABLE_INDEX = 24;
+    private static final int CARRIER_ID_INDEX = 25;
 
     @Override
     public void onCreate(Bundle icicle) {
@@ -312,6 +315,9 @@
         } else {
             mApnData = new ApnData(sProjection.length);
         }
+        final int carrierId = mApnData.getInteger(CARRIER_ID_INDEX,
+                TelephonyManager.UNKNOWN_CARRIER_ID);
+        mIsCarrierIdApn = (carrierId > TelephonyManager.UNKNOWN_CARRIER_ID);
 
         final boolean isUserEdited = mApnData.getInteger(EDITED_INDEX,
                 Telephony.Carriers.USER_EDITED) == Telephony.Carriers.USER_EDITED;
@@ -326,6 +332,10 @@
         } else if (!ArrayUtils.isEmpty(mReadOnlyApnFields)) {
             disableFields(mReadOnlyApnFields);
         }
+        // Make sure that a user cannot break carrier id APN matching
+        if (mIsCarrierIdApn) {
+            disableFieldsForCarrieridApn();
+        }
 
         for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
             getPreferenceScreen().getPreference(i).setOnPreferenceChangeListener(this);
@@ -517,6 +527,16 @@
         mMvnoMatchData.setEnabled(false);
     }
 
+    /**
+     * Disables fields for a carrier id APN to avoid breaking the match criteria
+     */
+    private void disableFieldsForCarrieridApn() {
+        mMcc.setEnabled(false);
+        mMnc.setEnabled(false);
+        mMvnoType.setEnabled(false);
+        mMvnoMatchData.setEnabled(false);
+    }
+
     @Override
     public int getMetricsCategory() {
         return SettingsEnums.APN_EDITOR;
@@ -1150,11 +1170,15 @@
         final String apn = checkNotSet(mApn.getText());
         final String mcc = checkNotSet(mMcc.getText());
         final String mnc = checkNotSet(mMnc.getText());
-
+        boolean doNotCheckMccMnc = mIsCarrierIdApn && TextUtils.isEmpty(mcc)
+                && TextUtils.isEmpty(mnc);
         if (TextUtils.isEmpty(name)) {
             errorMsg = getResources().getString(R.string.error_name_empty);
         } else if (TextUtils.isEmpty(apn)) {
             errorMsg = getResources().getString(R.string.error_apn_empty);
+        } else if (doNotCheckMccMnc) {
+            Log.d(TAG, "validateApnData: carrier id APN does not have mcc/mnc defined");
+            // no op, skip mcc mnc null check
         } else if (mcc == null || mcc.length() != 3) {
             errorMsg = getResources().getString(R.string.error_mcc_not3);
         } else if ((mnc == null || (mnc.length() & 0xFFFE) != 2)) {
diff --git a/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java b/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java
index 5f20894..ec48c82 100644
--- a/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java
+++ b/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java
@@ -184,7 +184,10 @@
         phoneTitle.setVisibility(info.isOpportunistic() ? View.GONE : View.VISIBLE);
 
         final TextView phoneNumber = view.findViewById(R.id.number_value);
-        phoneNumber.setText(DeviceInfoUtils.getBidiFormattedPhoneNumber(getContext(), info));
+        final String pn = DeviceInfoUtils.getBidiFormattedPhoneNumber(getContext(), info);
+        if (!TextUtils.isEmpty(pn)) {
+            phoneNumber.setText(pn);
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/password/ChooseLockSettingsHelper.java b/src/com/android/settings/password/ChooseLockSettingsHelper.java
index 77fcbed..e4d52ba 100644
--- a/src/com/android/settings/password/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/password/ChooseLockSettingsHelper.java
@@ -44,7 +44,6 @@
 
     private static final String TAG = "ChooseLockSettingsHelper";
 
-    public static final String EXTRA_KEY_TYPE = "type";
     public static final String EXTRA_KEY_PASSWORD = "password";
     public static final String EXTRA_KEY_RETURN_CREDENTIALS = "return_credentials";
     // Force the verifyCredential path instead of checkCredential path. This will be removed
@@ -191,7 +190,7 @@
         /**
          * @param returnCredentials if true, puts the following credentials into intent for
          *                          onActivityResult with the following keys:
-         *                          {@link #EXTRA_KEY_TYPE}, {@link #EXTRA_KEY_PASSWORD},
+         *                          {@link #EXTRA_KEY_PASSWORD},
          *                          {@link #EXTRA_KEY_CHALLENGE_TOKEN},
          *                          {@link #EXTRA_KEY_GK_PW_HANDLE}
          *                          Note that if this is true, this can only be called internally.
diff --git a/src/com/android/settings/password/ConfirmLockPassword.java b/src/com/android/settings/password/ConfirmLockPassword.java
index de32f13..2c90e55 100644
--- a/src/com/android/settings/password/ConfirmLockPassword.java
+++ b/src/com/android/settings/password/ConfirmLockPassword.java
@@ -29,7 +29,6 @@
 import android.os.Looper;
 import android.os.SystemClock;
 import android.os.UserManager;
-import android.os.storage.StorageManager;
 import android.text.Editable;
 import android.text.InputType;
 import android.text.TextUtils;
@@ -445,11 +444,6 @@
                         public void onChecked(boolean matched, int timeoutMs) {
                             mPendingLockCheck = null;
                             if (matched && isInternalActivity() && mReturnCredentials) {
-                                // TODO: get rid of EXTRA_KEY_TYPE, since EXTRA_KEY_PASSWORD already
-                                // distinguishes beteween PIN and password.
-                                intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
-                                                mIsAlpha ? StorageManager.CRYPT_TYPE_PASSWORD
-                                                         : StorageManager.CRYPT_TYPE_PIN);
                                 intent.putExtra(
                                         ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, credential);
                             }
diff --git a/src/com/android/settings/password/ConfirmLockPattern.java b/src/com/android/settings/password/ConfirmLockPattern.java
index ec5efcf..674660e 100644
--- a/src/com/android/settings/password/ConfirmLockPattern.java
+++ b/src/com/android/settings/password/ConfirmLockPattern.java
@@ -26,7 +26,6 @@
 import android.os.CountDownTimer;
 import android.os.SystemClock;
 import android.os.UserManager;
-import android.os.storage.StorageManager;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -506,8 +505,6 @@
                             public void onChecked(boolean matched, int timeoutMs) {
                                 mPendingLockCheck = null;
                                 if (matched && isInternalActivity() && mReturnCredentials) {
-                                    intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE,
-                                                    StorageManager.CRYPT_TYPE_PATTERN);
                                     intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD,
                                                     pattern);
                                 }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
index d8bdf32..528fbc3 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
@@ -168,10 +168,18 @@
                     break;
 
                 case MESSAGE_SCAN_ZXING_WIFI_FORMAT_SUCCESS:
+                    final Context context = getContext();
+                    if (context == null) {
+                        // Context may be null if the message is received after the Activity has
+                        // been destroyed
+                        Log.d(TAG, "Scan success but context is null");
+                        return;
+                    }
+
                     // We may get 2 WifiConfiguration if the QR code has no password in it,
                     // one for open network and one for enhanced open network.
                     final WifiManager wifiManager =
-                            getContext().getSystemService(WifiManager.class);
+                            context.getSystemService(WifiManager.class);
                     final WifiNetworkConfig qrCodeWifiNetworkConfig =
                             (WifiNetworkConfig)msg.obj;
                     final List<WifiConfiguration> qrCodeWifiConfigurations =
diff --git a/src/com/android/settings/wifi/p2p/WifiP2pSettings.java b/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
index a926360..c1365dd 100644
--- a/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
+++ b/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
@@ -353,6 +353,7 @@
             mWifiP2pManager.requestDeviceInfo(mChannel, WifiP2pSettings.this);
             mIsIgnoreInitConnectionInfoCallback = false;
             mWifiP2pManager.requestNetworkInfo(mChannel, networkInfo -> {
+                if (mChannel == null) return;
                 mWifiP2pManager.requestConnectionInfo(mChannel, wifip2pinfo -> {
                     if (!mIsIgnoreInitConnectionInfoCallback) {
                         if (networkInfo.isConnected()) {
diff --git a/src/com/android/settings/wifi/qrcode/QrCamera.java b/src/com/android/settings/wifi/qrcode/QrCamera.java
index 3865eb1..d07c543 100644
--- a/src/com/android/settings/wifi/qrcode/QrCamera.java
+++ b/src/com/android/settings/wifi/qrcode/QrCamera.java
@@ -124,6 +124,7 @@
         }
         if (mCamera != null) {
             mCamera.stopPreview();
+            releaseCamera();
         }
     }
 
diff --git a/tests/robotests/assets/exempt_not_implementing_index_provider b/tests/robotests/assets/exempt_not_implementing_index_provider
index d4a1c2e..6a1a1ff 100644
--- a/tests/robotests/assets/exempt_not_implementing_index_provider
+++ b/tests/robotests/assets/exempt_not_implementing_index_provider
@@ -15,7 +15,6 @@
 com.android.settings.applications.appinfo.WriteSettingsDetails
 com.android.settings.applications.AppLaunchSettings
 com.android.settings.applications.AppStorageSettings
-com.android.settings.applications.ConfirmConvertToFbe
 com.android.settings.applications.ProcessStatsDetail
 com.android.settings.applications.ProcessStatsSummary
 com.android.settings.applications.ProcessStatsUi
diff --git a/tests/robotests/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceControllerTest.java
index a1d479f..fcb3ea9 100644
--- a/tests/robotests/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceControllerTest.java
@@ -18,6 +18,8 @@
 
 import static com.android.settings.development.BluetoothA2dpHwOffloadPreferenceController
         .A2DP_OFFLOAD_DISABLED_PROPERTY;
+import static com.android.settings.development.BluetoothLeAudioHwOffloadPreferenceController
+        .LE_AUDIO_OFFLOAD_DISABLED_PROPERTY;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -62,15 +64,37 @@
     }
 
     @Test
-    public void onA2dpHwDialogConfirmed_shouldChangeProperty() {
+    public void onA2dpHwDialogConfirmedAsA2dpOffloadDisabled_shouldChangeProperty() {
         SystemProperties.set(A2DP_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(false));
+        mController.mChanged = true;
 
-        mController.onA2dpHwDialogConfirmed();
+        mController.onHwOffloadDialogConfirmed();
         final boolean mode = SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false);
         assertThat(mode).isTrue();
+    }
 
-        mController.onA2dpHwDialogConfirmed();
-        final boolean mode2 = SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false);
-        assertThat(mode2).isFalse();
+    @Test
+    public void onA2dpHwDialogConfirmedAsA2dpOffloadEnabled_shouldChangeProperty() {
+        SystemProperties.set(A2DP_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(true));
+        SystemProperties.set(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(true));
+
+        mController.mChanged = true;
+
+        mController.onHwOffloadDialogConfirmed();
+        final boolean a2dpMode = SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, true);
+        final boolean leAudioMode = SystemProperties
+                .getBoolean(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, true);
+        assertThat(a2dpMode).isFalse();
+        assertThat(leAudioMode).isFalse();
+    }
+
+    @Test
+    public void onA2dpHwDialogCanceled_shouldNotChangeProperty() {
+        SystemProperties.set(A2DP_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(false));
+        mController.mChanged = true;
+
+        mController.onHwOffloadDialogCanceled();
+        final boolean mode = SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false);
+        assertThat(mode).isFalse();
     }
 }
diff --git a/tests/robotests/src/com/android/settings/development/BluetoothLeAudioHwOffloadPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothLeAudioHwOffloadPreferenceControllerTest.java
new file mode 100644
index 0000000..c82df40e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/BluetoothLeAudioHwOffloadPreferenceControllerTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import static com.android.settings.development.BluetoothLeAudioHwOffloadPreferenceController
+        .LE_AUDIO_OFFLOAD_DISABLED_PROPERTY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.SystemProperties;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothLeAudioHwOffloadPreferenceControllerTest {
+
+    @Mock
+    private PreferenceScreen mPreferenceScreen;
+    @Mock
+    private DevelopmentSettingsDashboardFragment mFragment;
+
+    private Context mContext;
+    private SwitchPreference mPreference;
+    private BluetoothLeAudioHwOffloadPreferenceController mController;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mPreference = new SwitchPreference(mContext);
+        mController = spy(new BluetoothLeAudioHwOffloadPreferenceController(mContext, mFragment));
+        when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+            .thenReturn(mPreference);
+        mController.displayPreference(mPreferenceScreen);
+    }
+
+    @Test
+    public void onLeAudioHwDialogConfirmedAsLeAudioOffloadDisabled_shouldChangeProperty() {
+        SystemProperties.set(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(false));
+        mController.mChanged = true;
+
+        mController.onHwOffloadDialogConfirmed();
+        final boolean mode = SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, false);
+        assertThat(mode).isTrue();
+    }
+
+    @Test
+    public void onLeAudioHwDialogConfirmedAsLeAudioOffloadEnabled_shouldChangeProperty() {
+        SystemProperties.set(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(true));
+        mController.mChanged = true;
+
+        mController.onHwOffloadDialogConfirmed();
+        final boolean mode2 = SystemProperties.getBoolean(
+                LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, true);
+        assertThat(mode2).isFalse();
+    }
+
+    @Test
+    public void onLeAudioHwDialogCanceled_shouldNotChangeProperty() {
+        SystemProperties.set(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(false));
+        mController.mChanged = true;
+
+        mController.onHwOffloadDialogCanceled();
+        final boolean mode = SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, false);
+        assertThat(mode).isFalse();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
index 2d4082b..b8f44a2 100644
--- a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
@@ -202,9 +202,9 @@
         assertThat(dialog).isNotNull();
         ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
         assertThat(shadowDialog.getTitle()).isEqualTo(
-                mContext.getString(R.string.bluetooth_disable_a2dp_hw_offload_dialog_title));
+                mContext.getString(R.string.bluetooth_disable_hw_offload_dialog_title));
         assertThat(shadowDialog.getMessage()).isEqualTo(
-                mContext.getString(R.string.bluetooth_disable_a2dp_hw_offload_dialog_message));
+                mContext.getString(R.string.bluetooth_disable_hw_offload_dialog_message));
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/development/FileEncryptionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/FileEncryptionPreferenceControllerTest.java
deleted file mode 100644
index 0784a61..0000000
--- a/tests/robotests/src/com/android/settings/development/FileEncryptionPreferenceControllerTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.development;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.os.RemoteException;
-import android.os.storage.IStorageManager;
-import android.sysprop.CryptoProperties;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.util.ReflectionHelpers;
-
-@RunWith(RobolectricTestRunner.class)
-public class FileEncryptionPreferenceControllerTest {
-
-    @Mock
-    private Preference mPreference;
-    @Mock
-    private PreferenceScreen mPreferenceScreen;
-    @Mock
-    private IStorageManager mStorageManager;
-
-    private Context mContext;
-    private FileEncryptionPreferenceController mController;
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-        mController = new FileEncryptionPreferenceController(mContext);
-        when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
-            .thenReturn(mPreference);
-    }
-
-    @Test
-    public void isAvailable_storageManagerNull_shouldBeFalse() {
-        ReflectionHelpers.setField(mController, "mStorageManager", null);
-
-        assertThat(mController.isAvailable()).isFalse();
-    }
-
-    @Test
-    public void isAvailable_notConvertibleToFBE_shouldBeFalse() throws RemoteException {
-        ReflectionHelpers.setField(mController, "mStorageManager", mStorageManager);
-        when(mStorageManager.isConvertibleToFBE()).thenReturn(false);
-
-        assertThat(mController.isAvailable()).isFalse();
-    }
-
-    @Test
-    public void isAvailable_convertibleToFBE_shouldBeTrue() throws RemoteException {
-        ReflectionHelpers.setField(mController, "mStorageManager", mStorageManager);
-        when(mStorageManager.isConvertibleToFBE()).thenReturn(true);
-
-        assertThat(mController.isAvailable()).isTrue();
-    }
-
-    @Test
-    public void updateState_settingIsNotFile_shouldDoNothing() throws RemoteException {
-        ReflectionHelpers.setField(mController, "mStorageManager", mStorageManager);
-        when(mStorageManager.isConvertibleToFBE()).thenReturn(true);
-        mController.displayPreference(mPreferenceScreen);
-        CryptoProperties.type(CryptoProperties.type_values.NONE);
-
-        mController.updateState(mPreference);
-
-        verify(mPreference, never()).setEnabled(anyBoolean());
-        verify(mPreference, never()).setSummary(anyString());
-    }
-
-    @Test
-    public void updateState_settingIsFile_shouldSetSummaryAndDisablePreference()
-            throws RemoteException {
-        ReflectionHelpers.setField(mController, "mStorageManager", mStorageManager);
-        when(mStorageManager.isConvertibleToFBE()).thenReturn(true);
-        mController.displayPreference(mPreferenceScreen);
-        CryptoProperties.type(CryptoProperties.type_values.FILE);
-
-        mController.updateState(mPreference);
-
-        verify(mPreference).setEnabled(false);
-        verify(mPreference).setSummary(mContext.getString(R.string.convert_to_file_encryption_done));
-    }
-}