Loading AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ <uses-permission android:name="android.permission.HARDWARE_TEST" /> <uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED" /> <uses-permission android:name="android.permission.QUERY_AUDIO_STATE" /> <uses-permission android:name="android.permission.MASTER_CLEAR" /> <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" /> Loading res/values/strings.xml +13 −0 Original line number Diff line number Diff line Loading @@ -12072,6 +12072,19 @@ <!-- The summary of the head tracking [CHAR LIMIT=none] --> <string name="bluetooth_details_head_tracking_summary">Audio changes as you move your head to sound more natural</string> <!-- The title of the bluetooth audio device type selection [CHAR LIMIT=none] --> <string name="bluetooth_details_audio_device_types_title">Audio Device Type</string> <!-- The audio device type corresponding to unknown selected [CHAR LIMIT=none] --> <string name="bluetooth_details_audio_device_type_unknown">Unknown</string> <!-- The audio device type corresponding to none selected [CHAR LIMIT=none] --> <string name="bluetooth_details_audio_device_type_speaker">Speaker</string> <!-- The audio device type corresponding to speakers [CHAR LIMIT=none] --> <string name="bluetooth_details_audio_device_type_headphones">Headphones</string> <!-- The audio device type corresponding to car kit [CHAR LIMIT=none] --> <string name="bluetooth_details_audio_device_type_carkit">Car Kit</string> <!-- The audio device type corresponding to other device type [CHAR LIMIT=none] --> <string name="bluetooth_details_audio_device_type_other">Other</string> <!-- Developer Settings: Title for network bandwidth ingress rate limit [CHAR LIMIT=none] --> <string name="ingress_rate_limit_title">Network download rate limit</string> <!-- Developer Settings: Summary for network bandwidth ingress rate limit [CHAR LIMIT=none] --> res/xml/bluetooth_device_details_fragment.xml +3 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,9 @@ <PreferenceCategory android:key="device_controls_general" /> <PreferenceCategory android:key="bluetooth_audio_device_type_group"/> <PreferenceCategory android:key="spatial_audio_group"/> Loading src/com/android/settings/bluetooth/BluetoothDetailsAudioDeviceTypeController.java 0 → 100644 +180 −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.bluetooth; import static android.bluetooth.BluetoothDevice.DEVICE_TYPE_LE; import static android.media.AudioManager.AUDIO_DEVICE_CATEGORY_CARKIT; import static android.media.AudioManager.AUDIO_DEVICE_CATEGORY_HEADPHONES; import static android.media.AudioManager.AUDIO_DEVICE_CATEGORY_OTHER; import static android.media.AudioManager.AUDIO_DEVICE_CATEGORY_SPEAKER; import static android.media.AudioManager.AUDIO_DEVICE_CATEGORY_UNKNOWN; import android.content.Context; import android.media.AudioManager; import android.media.AudioManager.AudioDeviceCategory; import android.util.Log; import androidx.annotation.VisibleForTesting; import androidx.preference.ListPreference; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceScreen; 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.LocalBluetoothProfileManager; import com.android.settingslib.core.lifecycle.Lifecycle; /** * Controller responsible for the bluetooth audio device type selection */ public class BluetoothDetailsAudioDeviceTypeController extends BluetoothDetailsController implements Preference.OnPreferenceChangeListener { private static final String TAG = "BluetoothDetailsAudioDeviceTypeController"; private static final boolean DEBUG = false; private static final String KEY_BT_AUDIO_DEVICE_TYPE_GROUP = "bluetooth_audio_device_type_group"; private static final String KEY_BT_AUDIO_DEVICE_TYPE = "bluetooth_audio_device_type"; private final AudioManager mAudioManager; private ListPreference mAudioDeviceTypePreference; private final LocalBluetoothProfileManager mProfileManager; @VisibleForTesting PreferenceCategory mProfilesContainer; public BluetoothDetailsAudioDeviceTypeController( Context context, PreferenceFragmentCompat fragment, LocalBluetoothManager manager, CachedBluetoothDevice device, Lifecycle lifecycle) { super(context, fragment, device, lifecycle); mAudioManager = context.getSystemService(AudioManager.class); mProfileManager = manager.getProfileManager(); } @Override public boolean isAvailable() { // Available only for A2DP and BLE devices. A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile(); boolean a2dpProfileEnabled = false; if (a2dpProfile != null) { a2dpProfileEnabled = a2dpProfile.isEnabled(mCachedDevice.getDevice()); } LeAudioProfile leAudioProfile = mProfileManager.getLeAudioProfile(); boolean leAudioProfileEnabled = false; if (leAudioProfile != null) { leAudioProfileEnabled = leAudioProfile.isEnabled(mCachedDevice.getDevice()); } return a2dpProfileEnabled || leAudioProfileEnabled; } @Override public boolean onPreferenceChange(Preference preference, Object newValue) { if (preference instanceof ListPreference) { final ListPreference pref = (ListPreference) preference; final String key = pref.getKey(); if (key.equals(KEY_BT_AUDIO_DEVICE_TYPE)) { if (newValue instanceof String) { final String value = (String) newValue; final int index = pref.findIndexOfValue(value); if (index >= 0) { pref.setSummary(pref.getEntries()[index]); mAudioManager.setBluetoothAudioDeviceCategory(mCachedDevice.getAddress(), mCachedDevice.getDevice().getType() == DEVICE_TYPE_LE, Integer.parseInt(value)); } } return true; } } return false; } @Override public String getPreferenceKey() { return KEY_BT_AUDIO_DEVICE_TYPE_GROUP; } @Override protected void init(PreferenceScreen screen) { mProfilesContainer = screen.findPreference(getPreferenceKey()); refresh(); } @Override protected void refresh() { mAudioDeviceTypePreference = mProfilesContainer.findPreference( KEY_BT_AUDIO_DEVICE_TYPE); if (mAudioDeviceTypePreference == null) { createAudioDeviceTypePreference(mProfilesContainer.getContext()); mProfilesContainer.addPreference(mAudioDeviceTypePreference); } } @VisibleForTesting void createAudioDeviceTypePreference(Context context) { mAudioDeviceTypePreference = new ListPreference(context); mAudioDeviceTypePreference.setKey(KEY_BT_AUDIO_DEVICE_TYPE); mAudioDeviceTypePreference.setTitle( mContext.getString(R.string.bluetooth_details_audio_device_types_title)); mAudioDeviceTypePreference.setEntries(new CharSequence[]{ mContext.getString(R.string.bluetooth_details_audio_device_type_unknown), mContext.getString(R.string.bluetooth_details_audio_device_type_speaker), mContext.getString(R.string.bluetooth_details_audio_device_type_headphones), mContext.getString(R.string.bluetooth_details_audio_device_type_carkit), mContext.getString(R.string.bluetooth_details_audio_device_type_other), }); mAudioDeviceTypePreference.setEntryValues(new CharSequence[]{ Integer.toString(AUDIO_DEVICE_CATEGORY_UNKNOWN), Integer.toString(AUDIO_DEVICE_CATEGORY_SPEAKER), Integer.toString(AUDIO_DEVICE_CATEGORY_HEADPHONES), Integer.toString(AUDIO_DEVICE_CATEGORY_CARKIT), Integer.toString(AUDIO_DEVICE_CATEGORY_OTHER), }); @AudioDeviceCategory final int deviceCategory = mAudioManager.getBluetoothAudioDeviceCategory(mCachedDevice.getAddress(), mCachedDevice.getDevice().getType() == DEVICE_TYPE_LE); if (DEBUG) { Log.v(TAG, "getBluetoothAudioDeviceCategory() device: " + mCachedDevice.getDevice().getAnonymizedAddress() + ", has audio device category: " + deviceCategory); } mAudioDeviceTypePreference.setValue(Integer.toString(deviceCategory)); mAudioDeviceTypePreference.setSummary(mAudioDeviceTypePreference.getEntry()); mAudioDeviceTypePreference.setOnPreferenceChangeListener(this); } @VisibleForTesting ListPreference getAudioDeviceTypePreference() { return mAudioDeviceTypePreference; } } src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java +2 −0 Original line number Diff line number Diff line Loading @@ -300,6 +300,8 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment lifecycle)); controllers.add(new BluetoothDetailsCompanionAppsController(context, this, mCachedDevice, lifecycle)); controllers.add(new BluetoothDetailsAudioDeviceTypeController(context, this, mManager, mCachedDevice, lifecycle)); controllers.add(new BluetoothDetailsSpatialAudioController(context, this, mCachedDevice, lifecycle)); controllers.add(new BluetoothDetailsProfilesController(context, this, mManager, Loading Loading
AndroidManifest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ <uses-permission android:name="android.permission.HARDWARE_TEST" /> <uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED" /> <uses-permission android:name="android.permission.QUERY_AUDIO_STATE" /> <uses-permission android:name="android.permission.MASTER_CLEAR" /> <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" /> Loading
res/values/strings.xml +13 −0 Original line number Diff line number Diff line Loading @@ -12072,6 +12072,19 @@ <!-- The summary of the head tracking [CHAR LIMIT=none] --> <string name="bluetooth_details_head_tracking_summary">Audio changes as you move your head to sound more natural</string> <!-- The title of the bluetooth audio device type selection [CHAR LIMIT=none] --> <string name="bluetooth_details_audio_device_types_title">Audio Device Type</string> <!-- The audio device type corresponding to unknown selected [CHAR LIMIT=none] --> <string name="bluetooth_details_audio_device_type_unknown">Unknown</string> <!-- The audio device type corresponding to none selected [CHAR LIMIT=none] --> <string name="bluetooth_details_audio_device_type_speaker">Speaker</string> <!-- The audio device type corresponding to speakers [CHAR LIMIT=none] --> <string name="bluetooth_details_audio_device_type_headphones">Headphones</string> <!-- The audio device type corresponding to car kit [CHAR LIMIT=none] --> <string name="bluetooth_details_audio_device_type_carkit">Car Kit</string> <!-- The audio device type corresponding to other device type [CHAR LIMIT=none] --> <string name="bluetooth_details_audio_device_type_other">Other</string> <!-- Developer Settings: Title for network bandwidth ingress rate limit [CHAR LIMIT=none] --> <string name="ingress_rate_limit_title">Network download rate limit</string> <!-- Developer Settings: Summary for network bandwidth ingress rate limit [CHAR LIMIT=none] -->
res/xml/bluetooth_device_details_fragment.xml +3 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,9 @@ <PreferenceCategory android:key="device_controls_general" /> <PreferenceCategory android:key="bluetooth_audio_device_type_group"/> <PreferenceCategory android:key="spatial_audio_group"/> Loading
src/com/android/settings/bluetooth/BluetoothDetailsAudioDeviceTypeController.java 0 → 100644 +180 −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.bluetooth; import static android.bluetooth.BluetoothDevice.DEVICE_TYPE_LE; import static android.media.AudioManager.AUDIO_DEVICE_CATEGORY_CARKIT; import static android.media.AudioManager.AUDIO_DEVICE_CATEGORY_HEADPHONES; import static android.media.AudioManager.AUDIO_DEVICE_CATEGORY_OTHER; import static android.media.AudioManager.AUDIO_DEVICE_CATEGORY_SPEAKER; import static android.media.AudioManager.AUDIO_DEVICE_CATEGORY_UNKNOWN; import android.content.Context; import android.media.AudioManager; import android.media.AudioManager.AudioDeviceCategory; import android.util.Log; import androidx.annotation.VisibleForTesting; import androidx.preference.ListPreference; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceScreen; 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.LocalBluetoothProfileManager; import com.android.settingslib.core.lifecycle.Lifecycle; /** * Controller responsible for the bluetooth audio device type selection */ public class BluetoothDetailsAudioDeviceTypeController extends BluetoothDetailsController implements Preference.OnPreferenceChangeListener { private static final String TAG = "BluetoothDetailsAudioDeviceTypeController"; private static final boolean DEBUG = false; private static final String KEY_BT_AUDIO_DEVICE_TYPE_GROUP = "bluetooth_audio_device_type_group"; private static final String KEY_BT_AUDIO_DEVICE_TYPE = "bluetooth_audio_device_type"; private final AudioManager mAudioManager; private ListPreference mAudioDeviceTypePreference; private final LocalBluetoothProfileManager mProfileManager; @VisibleForTesting PreferenceCategory mProfilesContainer; public BluetoothDetailsAudioDeviceTypeController( Context context, PreferenceFragmentCompat fragment, LocalBluetoothManager manager, CachedBluetoothDevice device, Lifecycle lifecycle) { super(context, fragment, device, lifecycle); mAudioManager = context.getSystemService(AudioManager.class); mProfileManager = manager.getProfileManager(); } @Override public boolean isAvailable() { // Available only for A2DP and BLE devices. A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile(); boolean a2dpProfileEnabled = false; if (a2dpProfile != null) { a2dpProfileEnabled = a2dpProfile.isEnabled(mCachedDevice.getDevice()); } LeAudioProfile leAudioProfile = mProfileManager.getLeAudioProfile(); boolean leAudioProfileEnabled = false; if (leAudioProfile != null) { leAudioProfileEnabled = leAudioProfile.isEnabled(mCachedDevice.getDevice()); } return a2dpProfileEnabled || leAudioProfileEnabled; } @Override public boolean onPreferenceChange(Preference preference, Object newValue) { if (preference instanceof ListPreference) { final ListPreference pref = (ListPreference) preference; final String key = pref.getKey(); if (key.equals(KEY_BT_AUDIO_DEVICE_TYPE)) { if (newValue instanceof String) { final String value = (String) newValue; final int index = pref.findIndexOfValue(value); if (index >= 0) { pref.setSummary(pref.getEntries()[index]); mAudioManager.setBluetoothAudioDeviceCategory(mCachedDevice.getAddress(), mCachedDevice.getDevice().getType() == DEVICE_TYPE_LE, Integer.parseInt(value)); } } return true; } } return false; } @Override public String getPreferenceKey() { return KEY_BT_AUDIO_DEVICE_TYPE_GROUP; } @Override protected void init(PreferenceScreen screen) { mProfilesContainer = screen.findPreference(getPreferenceKey()); refresh(); } @Override protected void refresh() { mAudioDeviceTypePreference = mProfilesContainer.findPreference( KEY_BT_AUDIO_DEVICE_TYPE); if (mAudioDeviceTypePreference == null) { createAudioDeviceTypePreference(mProfilesContainer.getContext()); mProfilesContainer.addPreference(mAudioDeviceTypePreference); } } @VisibleForTesting void createAudioDeviceTypePreference(Context context) { mAudioDeviceTypePreference = new ListPreference(context); mAudioDeviceTypePreference.setKey(KEY_BT_AUDIO_DEVICE_TYPE); mAudioDeviceTypePreference.setTitle( mContext.getString(R.string.bluetooth_details_audio_device_types_title)); mAudioDeviceTypePreference.setEntries(new CharSequence[]{ mContext.getString(R.string.bluetooth_details_audio_device_type_unknown), mContext.getString(R.string.bluetooth_details_audio_device_type_speaker), mContext.getString(R.string.bluetooth_details_audio_device_type_headphones), mContext.getString(R.string.bluetooth_details_audio_device_type_carkit), mContext.getString(R.string.bluetooth_details_audio_device_type_other), }); mAudioDeviceTypePreference.setEntryValues(new CharSequence[]{ Integer.toString(AUDIO_DEVICE_CATEGORY_UNKNOWN), Integer.toString(AUDIO_DEVICE_CATEGORY_SPEAKER), Integer.toString(AUDIO_DEVICE_CATEGORY_HEADPHONES), Integer.toString(AUDIO_DEVICE_CATEGORY_CARKIT), Integer.toString(AUDIO_DEVICE_CATEGORY_OTHER), }); @AudioDeviceCategory final int deviceCategory = mAudioManager.getBluetoothAudioDeviceCategory(mCachedDevice.getAddress(), mCachedDevice.getDevice().getType() == DEVICE_TYPE_LE); if (DEBUG) { Log.v(TAG, "getBluetoothAudioDeviceCategory() device: " + mCachedDevice.getDevice().getAnonymizedAddress() + ", has audio device category: " + deviceCategory); } mAudioDeviceTypePreference.setValue(Integer.toString(deviceCategory)); mAudioDeviceTypePreference.setSummary(mAudioDeviceTypePreference.getEntry()); mAudioDeviceTypePreference.setOnPreferenceChangeListener(this); } @VisibleForTesting ListPreference getAudioDeviceTypePreference() { return mAudioDeviceTypePreference; } }
src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java +2 −0 Original line number Diff line number Diff line Loading @@ -300,6 +300,8 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment lifecycle)); controllers.add(new BluetoothDetailsCompanionAppsController(context, this, mCachedDevice, lifecycle)); controllers.add(new BluetoothDetailsAudioDeviceTypeController(context, this, mManager, mCachedDevice, lifecycle)); controllers.add(new BluetoothDetailsSpatialAudioController(context, this, mCachedDevice, lifecycle)); controllers.add(new BluetoothDetailsProfilesController(context, this, mManager, Loading