Loading res/values/strings.xml +5 −0 Original line number Diff line number Diff line Loading @@ -365,6 +365,11 @@ <!-- Summary of checkbox for enabling Bluetooth LE audio [CHAR LIMIT=none]--> <string name="bluetooth_enable_leaudio_summary">Enables Bluetooth LE audio feature if the device supports LE audio hardware capabilities.</string> <!-- Setting Checkbox title for enabling Bluetooth LE Audio Allow List. [CHAR LIMIT=none] --> <string name="bluetooth_enable_leaudio_allow_list">Enable Bluetooth LE audio Allow List</string> <!-- Summary of checkbox for enabling Bluetooth LE audio Allow List [CHAR LIMIT=none]--> <string name="bluetooth_enable_leaudio_allow_list_summary">Enable Bluetooth LE audio allow list feature.</string> <!-- Title for Bluetooth device group with media capability group [CHAR LIMIT=none]--> <string name="connected_device_media_device_title">Media devices</string> <!-- Title for Bluetooth device group with media capability group [CHAR LIMIT=none]--> res/xml/development_settings.xml +5 −0 Original line number Diff line number Diff line Loading @@ -344,6 +344,11 @@ android:title="@string/bluetooth_enable_leaudio" android:summary="@string/bluetooth_enable_leaudio_summary" /> <SwitchPreference android:key="bluetooth_enable_leaudio_allow_list" android:title="@string/bluetooth_enable_leaudio_allow_list" android:summary="@string/bluetooth_enable_leaudio_allow_list_summary" /> <SwitchPreference android:key="bluetooth_disable_le_audio_hw_offload" android:title="@string/bluetooth_disable_le_audio_hw_offload" /> Loading src/com/android/settings/development/BluetoothLeAudioAllowListPreferenceController.java 0 → 100644 +129 −0 Original line number Diff line number Diff line /* * 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 android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothStatusCodes; 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 feature */ public class BluetoothLeAudioAllowListPreferenceController extends DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin { private static final String PREFERENCE_KEY = "bluetooth_enable_leaudio_allow_list"; private static final String LE_AUDIO_ALLOW_LIST_SWITCH_SUPPORT_PROPERTY = "ro.bluetooth.leaudio_allow_list.supported"; @VisibleForTesting static final String LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY = "persist.bluetooth.leaudio.enable_allow_list"; private static final String LE_AUDIO_DYNAMIC_SWITCH_PROPERTY = "ro.bluetooth.leaudio_switcher.supported"; @VisibleForTesting static final String LE_AUDIO_DYNAMIC_ENABLED_PROPERTY = "persist.bluetooth.leaudio_switcher.enabled"; @VisibleForTesting BluetoothAdapter mBluetoothAdapter; private final DevelopmentSettingsDashboardFragment mFragment; @VisibleForTesting boolean mChanged = false; public BluetoothLeAudioAllowListPreferenceController(Context context, DevelopmentSettingsDashboardFragment fragment) { super(context); mFragment = fragment; mBluetoothAdapter = context.getSystemService(BluetoothManager.class).getAdapter(); } @Override public String getPreferenceKey() { return PREFERENCE_KEY; } @Override public boolean onPreferenceChange(Preference preference, Object newValue) { BluetoothRebootDialog.show(mFragment); mChanged = true; return false; } @Override public void updateState(Preference preference) { if (mBluetoothAdapter == null) { return; } int leAudioSupportedState = mBluetoothAdapter.isLeAudioSupported(); boolean leAudioEnabled = false; if ((leAudioSupportedState == BluetoothStatusCodes.FEATURE_SUPPORTED) || (leAudioSupportedState == BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED && SystemProperties.getBoolean(LE_AUDIO_DYNAMIC_SWITCH_PROPERTY, false) && SystemProperties.getBoolean(LE_AUDIO_DYNAMIC_ENABLED_PROPERTY, false))) { leAudioEnabled = true; } final boolean leAudioAllowListSupport = SystemProperties.getBoolean(LE_AUDIO_ALLOW_LIST_SWITCH_SUPPORT_PROPERTY, false); if (leAudioEnabled && leAudioAllowListSupport) { final boolean leAudioAllowListEnabled = SystemProperties.getBoolean(LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY, false); ((SwitchPreference) mPreference).setChecked(leAudioAllowListEnabled); } else { mPreference.setEnabled(false); ((SwitchPreference) mPreference).setChecked(false); } } /** * Called when the RebootDialog confirm is clicked. */ public void onRebootDialogConfirmed() { if (!mChanged) { return; } final boolean leAudioAllowListEnabled = SystemProperties.getBoolean(LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY, false); SystemProperties.set(LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY, Boolean.toString(!leAudioAllowListEnabled)); } /** * Called when the RebootDialog cancel is clicked. */ public void onRebootDialogCanceled() { mChanged = false; } } src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java +11 −0 Original line number Diff line number Diff line Loading @@ -387,6 +387,11 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra getDevelopmentOptionsController( BluetoothLeAudioPreferenceController.class); leAudioFeatureController.onRebootDialogConfirmed(); final BluetoothLeAudioAllowListPreferenceController leAudioAllowListController = getDevelopmentOptionsController( BluetoothLeAudioAllowListPreferenceController.class); leAudioAllowListController.onRebootDialogConfirmed(); } @Override Loading @@ -404,6 +409,11 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra getDevelopmentOptionsController( BluetoothLeAudioPreferenceController.class); leAudioFeatureController.onRebootDialogCanceled(); final BluetoothLeAudioAllowListPreferenceController leAudioAllowListController = getDevelopmentOptionsController( BluetoothLeAudioAllowListPreferenceController.class); leAudioAllowListController.onRebootDialogCanceled(); } @Override Loading Loading @@ -600,6 +610,7 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra controllers.add(new BluetoothAvrcpVersionPreferenceController(context)); controllers.add(new BluetoothMapVersionPreferenceController(context)); controllers.add(new BluetoothLeAudioPreferenceController(context, fragment)); controllers.add(new BluetoothLeAudioAllowListPreferenceController(context, fragment)); controllers.add(new BluetoothA2dpHwOffloadPreferenceController(context, fragment)); controllers.add(new BluetoothLeAudioHwOffloadPreferenceController(context, fragment)); controllers.add(new BluetoothMaxConnectedAudioDevicesPreferenceController(context)); Loading tests/robotests/src/com/android/settings/development/BluetoothLeAudioAllowListPreferenceControllerTest.java 0 → 100644 +106 −0 Original line number Diff line number Diff line /* * 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 android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED; import static com.android.settings.development.BluetoothLeAudioAllowListPreferenceController .LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; 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 BluetoothLeAudioAllowListPreferenceControllerTest { @Mock private PreferenceScreen mPreferenceScreen; @Mock private DevelopmentSettingsDashboardFragment mFragment; @Mock private BluetoothAdapter mBluetoothAdapter; private Context mContext; private SwitchPreference mPreference; private BluetoothLeAudioPreferenceController mController; @Before public void setup() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; mPreference = new SwitchPreference(mContext); mController = spy(new BluetoothLeAudioPreferenceController(mContext, mFragment)); when(mPreferenceScreen.findPreference(mController.getPreferenceKey())) .thenReturn(mPreference); mController.mBluetoothAdapter = mBluetoothAdapter; mController.displayPreference(mPreferenceScreen); when(mBluetoothAdapter.isLeAudioSupported()) .thenReturn(FEATURE_SUPPORTED); } @Test public void onRebootDialogConfirmedAsLeAudioAllowListDisabled_shouldSwitchStatus() { SystemProperties.set(LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY, Boolean.toString(false)); mController.mChanged = true; mController.onRebootDialogConfirmed(); final boolean mode = SystemProperties.getBoolean( LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY, false); assertThat(mode).isFalse(); } @Test public void onRebootDialogConfirmedAsLeAudioAllowListEnabled_shouldSwitchStatus() { SystemProperties.set(LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY, Boolean.toString(true)); mController.mChanged = true; mController.onRebootDialogConfirmed(); final boolean status = SystemProperties.getBoolean( LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY, false); assertThat(status).isTrue(); } @Test public void onRebootDialogCanceled_shouldNotSwitchStatus() { SystemProperties.set(LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY, Boolean.toString(false)); mController.mChanged = true; mController.onRebootDialogCanceled(); final boolean status = SystemProperties.getBoolean( LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY, false); assertThat(status).isFalse(); } } Loading
res/values/strings.xml +5 −0 Original line number Diff line number Diff line Loading @@ -365,6 +365,11 @@ <!-- Summary of checkbox for enabling Bluetooth LE audio [CHAR LIMIT=none]--> <string name="bluetooth_enable_leaudio_summary">Enables Bluetooth LE audio feature if the device supports LE audio hardware capabilities.</string> <!-- Setting Checkbox title for enabling Bluetooth LE Audio Allow List. [CHAR LIMIT=none] --> <string name="bluetooth_enable_leaudio_allow_list">Enable Bluetooth LE audio Allow List</string> <!-- Summary of checkbox for enabling Bluetooth LE audio Allow List [CHAR LIMIT=none]--> <string name="bluetooth_enable_leaudio_allow_list_summary">Enable Bluetooth LE audio allow list feature.</string> <!-- Title for Bluetooth device group with media capability group [CHAR LIMIT=none]--> <string name="connected_device_media_device_title">Media devices</string> <!-- Title for Bluetooth device group with media capability group [CHAR LIMIT=none]-->
res/xml/development_settings.xml +5 −0 Original line number Diff line number Diff line Loading @@ -344,6 +344,11 @@ android:title="@string/bluetooth_enable_leaudio" android:summary="@string/bluetooth_enable_leaudio_summary" /> <SwitchPreference android:key="bluetooth_enable_leaudio_allow_list" android:title="@string/bluetooth_enable_leaudio_allow_list" android:summary="@string/bluetooth_enable_leaudio_allow_list_summary" /> <SwitchPreference android:key="bluetooth_disable_le_audio_hw_offload" android:title="@string/bluetooth_disable_le_audio_hw_offload" /> Loading
src/com/android/settings/development/BluetoothLeAudioAllowListPreferenceController.java 0 → 100644 +129 −0 Original line number Diff line number Diff line /* * 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 android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothStatusCodes; 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 feature */ public class BluetoothLeAudioAllowListPreferenceController extends DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin { private static final String PREFERENCE_KEY = "bluetooth_enable_leaudio_allow_list"; private static final String LE_AUDIO_ALLOW_LIST_SWITCH_SUPPORT_PROPERTY = "ro.bluetooth.leaudio_allow_list.supported"; @VisibleForTesting static final String LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY = "persist.bluetooth.leaudio.enable_allow_list"; private static final String LE_AUDIO_DYNAMIC_SWITCH_PROPERTY = "ro.bluetooth.leaudio_switcher.supported"; @VisibleForTesting static final String LE_AUDIO_DYNAMIC_ENABLED_PROPERTY = "persist.bluetooth.leaudio_switcher.enabled"; @VisibleForTesting BluetoothAdapter mBluetoothAdapter; private final DevelopmentSettingsDashboardFragment mFragment; @VisibleForTesting boolean mChanged = false; public BluetoothLeAudioAllowListPreferenceController(Context context, DevelopmentSettingsDashboardFragment fragment) { super(context); mFragment = fragment; mBluetoothAdapter = context.getSystemService(BluetoothManager.class).getAdapter(); } @Override public String getPreferenceKey() { return PREFERENCE_KEY; } @Override public boolean onPreferenceChange(Preference preference, Object newValue) { BluetoothRebootDialog.show(mFragment); mChanged = true; return false; } @Override public void updateState(Preference preference) { if (mBluetoothAdapter == null) { return; } int leAudioSupportedState = mBluetoothAdapter.isLeAudioSupported(); boolean leAudioEnabled = false; if ((leAudioSupportedState == BluetoothStatusCodes.FEATURE_SUPPORTED) || (leAudioSupportedState == BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED && SystemProperties.getBoolean(LE_AUDIO_DYNAMIC_SWITCH_PROPERTY, false) && SystemProperties.getBoolean(LE_AUDIO_DYNAMIC_ENABLED_PROPERTY, false))) { leAudioEnabled = true; } final boolean leAudioAllowListSupport = SystemProperties.getBoolean(LE_AUDIO_ALLOW_LIST_SWITCH_SUPPORT_PROPERTY, false); if (leAudioEnabled && leAudioAllowListSupport) { final boolean leAudioAllowListEnabled = SystemProperties.getBoolean(LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY, false); ((SwitchPreference) mPreference).setChecked(leAudioAllowListEnabled); } else { mPreference.setEnabled(false); ((SwitchPreference) mPreference).setChecked(false); } } /** * Called when the RebootDialog confirm is clicked. */ public void onRebootDialogConfirmed() { if (!mChanged) { return; } final boolean leAudioAllowListEnabled = SystemProperties.getBoolean(LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY, false); SystemProperties.set(LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY, Boolean.toString(!leAudioAllowListEnabled)); } /** * Called when the RebootDialog cancel is clicked. */ public void onRebootDialogCanceled() { mChanged = false; } }
src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java +11 −0 Original line number Diff line number Diff line Loading @@ -387,6 +387,11 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra getDevelopmentOptionsController( BluetoothLeAudioPreferenceController.class); leAudioFeatureController.onRebootDialogConfirmed(); final BluetoothLeAudioAllowListPreferenceController leAudioAllowListController = getDevelopmentOptionsController( BluetoothLeAudioAllowListPreferenceController.class); leAudioAllowListController.onRebootDialogConfirmed(); } @Override Loading @@ -404,6 +409,11 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra getDevelopmentOptionsController( BluetoothLeAudioPreferenceController.class); leAudioFeatureController.onRebootDialogCanceled(); final BluetoothLeAudioAllowListPreferenceController leAudioAllowListController = getDevelopmentOptionsController( BluetoothLeAudioAllowListPreferenceController.class); leAudioAllowListController.onRebootDialogCanceled(); } @Override Loading Loading @@ -600,6 +610,7 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra controllers.add(new BluetoothAvrcpVersionPreferenceController(context)); controllers.add(new BluetoothMapVersionPreferenceController(context)); controllers.add(new BluetoothLeAudioPreferenceController(context, fragment)); controllers.add(new BluetoothLeAudioAllowListPreferenceController(context, fragment)); controllers.add(new BluetoothA2dpHwOffloadPreferenceController(context, fragment)); controllers.add(new BluetoothLeAudioHwOffloadPreferenceController(context, fragment)); controllers.add(new BluetoothMaxConnectedAudioDevicesPreferenceController(context)); Loading
tests/robotests/src/com/android/settings/development/BluetoothLeAudioAllowListPreferenceControllerTest.java 0 → 100644 +106 −0 Original line number Diff line number Diff line /* * 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 android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED; import static com.android.settings.development.BluetoothLeAudioAllowListPreferenceController .LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; 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 BluetoothLeAudioAllowListPreferenceControllerTest { @Mock private PreferenceScreen mPreferenceScreen; @Mock private DevelopmentSettingsDashboardFragment mFragment; @Mock private BluetoothAdapter mBluetoothAdapter; private Context mContext; private SwitchPreference mPreference; private BluetoothLeAudioPreferenceController mController; @Before public void setup() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; mPreference = new SwitchPreference(mContext); mController = spy(new BluetoothLeAudioPreferenceController(mContext, mFragment)); when(mPreferenceScreen.findPreference(mController.getPreferenceKey())) .thenReturn(mPreference); mController.mBluetoothAdapter = mBluetoothAdapter; mController.displayPreference(mPreferenceScreen); when(mBluetoothAdapter.isLeAudioSupported()) .thenReturn(FEATURE_SUPPORTED); } @Test public void onRebootDialogConfirmedAsLeAudioAllowListDisabled_shouldSwitchStatus() { SystemProperties.set(LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY, Boolean.toString(false)); mController.mChanged = true; mController.onRebootDialogConfirmed(); final boolean mode = SystemProperties.getBoolean( LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY, false); assertThat(mode).isFalse(); } @Test public void onRebootDialogConfirmedAsLeAudioAllowListEnabled_shouldSwitchStatus() { SystemProperties.set(LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY, Boolean.toString(true)); mController.mChanged = true; mController.onRebootDialogConfirmed(); final boolean status = SystemProperties.getBoolean( LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY, false); assertThat(status).isTrue(); } @Test public void onRebootDialogCanceled_shouldNotSwitchStatus() { SystemProperties.set(LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY, Boolean.toString(false)); mController.mChanged = true; mController.onRebootDialogCanceled(); final boolean status = SystemProperties.getBoolean( LE_AUDIO_ALLOW_LIST_ENABLED_PROPERTY, false); assertThat(status).isFalse(); } }