Merge "Import translations. DO NOT MERGE" into pi-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 90fe8ad..1e6358c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -402,6 +402,17 @@
     <!-- Summary for bluetooth item in connection detail page. (phone)-->
     <string name="bluetooth_pref_summary" product="default">Allow your phone to communicate with nearby Bluetooth devices</string>
 
+    <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=40] -->
+    <string name="bluetooth_disable_a2dp_hw_offload">Disable Bluetooth A2DP hardware offload</string>
+    <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=20] -->
+    <string name="bluetooth_disable_a2dp_hw_offload_dialog_title">Restart Device?</string>
+    <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=60] -->
+    <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=10] -->
+    <string name="bluetooth_disable_a2dp_hw_offload_dialog_confirm">Restart</string>
+    <!-- UI debug setting: Disable Bluetooth A2DP hardware offload [CHAR LIMIT=10] -->
+    <string name="bluetooth_disable_a2dp_hw_offload_dialog_cancel">Cancel</string>
+
     <!-- Title for Bluetooth device group with media capability group [CHAR LIMIT=none]-->
     <string name="connected_device_available_media_title">Available media devices</string>
     <!-- Title for Bluetooth device group with media capability group [CHAR LIMIT=none]-->
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index c7d49de..872837e 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -258,6 +258,10 @@
             android:title="@string/bluetooth_disable_absolute_volume"
             android:summary="@string/bluetooth_disable_absolute_volume_summary" />
 
+        <SwitchPreference
+            android:key="bluetooth_disable_a2dp_hw_offload"
+            android:title="@string/bluetooth_disable_a2dp_hw_offload" />
+
         <ListPreference
             android:key="bluetooth_select_avrcp_version"
             android:title="@string/bluetooth_select_avrcp_version_string"
diff --git a/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java b/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java
new file mode 100644
index 0000000..553a63e
--- /dev/null
+++ b/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.support.annotation.VisibleForTesting;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+public class BluetoothA2dpHwOffloadPreferenceController extends DeveloperOptionsPreferenceController
+        implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
+
+    private static final String PREFERENCE_KEY = "bluetooth_disable_a2dp_hw_offload";
+    private final DevelopmentSettingsDashboardFragment mFragment;
+
+    static final String A2DP_OFFLOAD_DISABLED_PROPERTY = "persist.bluetooth.a2dp_offload.disabled";
+    static final String A2DP_OFFLOAD_SUPPORTED_PROPERTY = "ro.bluetooth.a2dp_offload.supported";
+
+    public BluetoothA2dpHwOffloadPreferenceController(Context context,
+            DevelopmentSettingsDashboardFragment fragment) {
+        super(context);
+        mFragment = fragment;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return PREFERENCE_KEY;
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        BluetoothA2dpHwOffloadRebootDialog.show(mFragment, this);
+        return false;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        final boolean offloadSupported =
+                SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false);
+        if (offloadSupported) {
+            final boolean offloadDisabled =
+                    SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false);
+            ((SwitchPreference) mPreference).setChecked(offloadDisabled);
+        } else {
+            mPreference.setEnabled(false);
+            ((SwitchPreference) mPreference).setChecked(true);
+        }
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchDisabled() {
+        super.onDeveloperOptionsSwitchDisabled();
+        ((SwitchPreference) mPreference).setChecked(true);
+        SystemProperties.set(A2DP_OFFLOAD_DISABLED_PROPERTY, "true");
+    }
+
+    public void onA2dpHwDialogConfirmed() {
+        final boolean offloadDisabled =
+                SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false);
+        SystemProperties.set(A2DP_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(!offloadDisabled));
+    }
+
+}
diff --git a/src/com/android/settings/development/BluetoothA2dpHwOffloadRebootDialog.java b/src/com/android/settings/development/BluetoothA2dpHwOffloadRebootDialog.java
new file mode 100644
index 0000000..6fe03dd
--- /dev/null
+++ b/src/com/android/settings/development/BluetoothA2dpHwOffloadRebootDialog.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.FragmentManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.os.PowerManager;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+public class BluetoothA2dpHwOffloadRebootDialog extends InstrumentedDialogFragment
+        implements DialogInterface.OnClickListener {
+
+    public static final String TAG = "BluetoothA2dpHwOffloadReboot";
+
+    public static void show(DevelopmentSettingsDashboardFragment host,
+            BluetoothA2dpHwOffloadPreferenceController controller) {
+        final FragmentManager manager = host.getActivity().getFragmentManager();
+        if (manager.findFragmentByTag(TAG) == null) {
+            final BluetoothA2dpHwOffloadRebootDialog dialog =
+                    new BluetoothA2dpHwOffloadRebootDialog();
+            dialog.setTargetFragment(host, 0 /* requestCode */);
+            dialog.show(manager, TAG);
+        }
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsProto.MetricsEvent.DIALOG_BLUETOOTH_DISABLE_A2DP_HW_OFFLOAD;
+    }
+
+    @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)
+                .setPositiveButton(
+                        R.string.bluetooth_disable_a2dp_hw_offload_dialog_confirm, this)
+                .setNegativeButton(
+                        R.string.bluetooth_disable_a2dp_hw_offload_dialog_cancel, this)
+                .create();
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        final OnA2dpHwDialogConfirmedListener host =
+                (OnA2dpHwDialogConfirmedListener) getTargetFragment();
+        if (host == null) {
+            return;
+        }
+        if (which == DialogInterface.BUTTON_POSITIVE) {
+            host.onA2dpHwDialogConfirmed();
+            PowerManager pm = getContext().getSystemService(PowerManager.class);
+            pm.reboot(null);
+        }
+    }
+
+    public interface OnA2dpHwDialogConfirmedListener {
+        /**
+         * Called when the user presses reboot on the warning dialog.
+         */
+        void onA2dpHwDialogConfirmed();
+    }
+}
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index e90b53c..bc749c1 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -56,7 +56,8 @@
 
 public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFragment
         implements SwitchBar.OnSwitchChangeListener, OemUnlockDialogHost, AdbDialogHost,
-        AdbClearKeysDialogHost, LogPersistDialogHost {
+        AdbClearKeysDialogHost, LogPersistDialogHost,
+        BluetoothA2dpHwOffloadRebootDialog.OnA2dpHwDialogConfirmedListener {
 
     private static final String TAG = "DevSettingsDashboard";
 
@@ -270,6 +271,13 @@
     }
 
     @Override
+    public void onA2dpHwDialogConfirmed() {
+        final BluetoothA2dpHwOffloadPreferenceController controller =
+                getDevelopmentOptionsController(BluetoothA2dpHwOffloadPreferenceController.class);
+        controller.onA2dpHwDialogConfirmed();
+    }
+
+    @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
         boolean handledResult = false;
         for (AbstractPreferenceController controller : mPreferenceControllers) {
@@ -406,6 +414,7 @@
         controllers.add(new BluetoothDeviceNoNamePreferenceController(context));
         controllers.add(new BluetoothAbsoluteVolumePreferenceController(context));
         controllers.add(new BluetoothAvrcpVersionPreferenceController(context));
+        controllers.add(new BluetoothA2dpHwOffloadPreferenceController(context, fragment));
         controllers.add(new BluetoothAudioCodecPreferenceController(context, lifecycle,
                 bluetoothA2dpConfigStore));
         controllers.add(new BluetoothAudioSampleRatePreferenceController(context, lifecycle,
diff --git a/tests/robotests/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceControllerTest.java
new file mode 100644
index 0000000..28d6a47
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceControllerTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import static com.android.settings.development.BluetoothA2dpHwOffloadPreferenceController.A2DP_OFFLOAD_DISABLED_PROPERTY;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class BluetoothA2dpHwOffloadPreferenceControllerTest {
+
+    @Mock
+    private PreferenceScreen mPreferenceScreen;
+    @Mock
+    private DevelopmentSettingsDashboardFragment mFragment;
+
+    private Context mContext;
+    private SwitchPreference mPreference;
+    private BluetoothA2dpHwOffloadPreferenceController mController;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mPreference = new SwitchPreference(mContext);
+        mController = spy(new BluetoothA2dpHwOffloadPreferenceController(mContext, mFragment));
+        when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+            .thenReturn(mPreference);
+        mController.displayPreference(mPreferenceScreen);
+    }
+
+    @Test
+    public void onA2dpHwDialogConfirmed_shouldChangeProperty() {
+        SystemProperties.set(A2DP_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(false));
+
+        mController.onA2dpHwDialogConfirmed();
+        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();
+    }
+}