Loading android/app/src/com/android/bluetooth/btservice/AdapterService.java +13 −51 Original line number Diff line number Diff line Loading @@ -96,7 +96,6 @@ import android.os.PowerManager; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.DeviceConfig; Loading Loading @@ -208,7 +207,6 @@ public class AdapterService extends Service { private final ArrayList<ProfileService> mRegisteredProfiles = new ArrayList<>(); private final ArrayList<ProfileService> mRunningProfiles = new ArrayList<>(); private HashSet<String> mLeAudioAllowDevices = new HashSet<>(); private boolean mLeAudioAllowListEnabled = false; public static final String ACTION_LOAD_ADAPTER_PROPERTIES = "com.android.bluetooth.btservice.action.LOAD_ADAPTER_PROPERTIES"; Loading Loading @@ -236,8 +234,7 @@ public class AdapterService extends Service { static final String LOCAL_MAC_ADDRESS_PERM = android.Manifest.permission.LOCAL_MAC_ADDRESS; static final String RECEIVE_MAP_PERM = android.Manifest.permission.RECEIVE_BLUETOOTH_MAP; static final String BLUETOOTH_LE_AUDIO_ALLOW_LIST = "persist.bluetooth.leaudio.allow_list"; static final String BLUETOOTH_ENABLE_LE_AUDIO_ALLOW_LIST = "persist.bluetooth.leaudio.enable_allow_list"; static final String PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE = "phonebook_access_permission"; static final String MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE = "message_access_permission"; Loading Loading @@ -673,7 +670,6 @@ public class AdapterService extends Service { mBluetoothQualityReportNativeInterface.init(); mSdpManager = SdpManager.init(this); loadLeAudioAllowDevices(); mDatabaseManager = new DatabaseManager(this); mDatabaseManager.start(MetadataDatabase.createDatabase(this)); Loading Loading @@ -1554,8 +1550,7 @@ public class AdapterService extends Service { return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.COORDINATED_SET); } if (profile == BluetoothProfile.LE_AUDIO) { return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.LE_AUDIO) && isLeAudioAllowed(device); return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.LE_AUDIO); } if (profile == BluetoothProfile.HAP_CLIENT) { return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HAS); Loading Loading @@ -7503,15 +7498,16 @@ public class AdapterService extends Service { ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_INTERVAL_MS); mLeAudioAllowList = properties.getString(LE_AUDIO_ALLOW_LIST, ""); if (mLeAudioAllowList.isEmpty()) { List<String> leAudioAllowDevices = BluetoothProperties.le_audio_allow_list(); if (leAudioAllowDevices != null && !leAudioAllowDevices.isEmpty()) { mLeAudioAllowDevices = new HashSet<String>(leAudioAllowDevices); if (!mLeAudioAllowList.isEmpty()) { List<String> leAudioAllowlistFromDeviceConfig = Arrays.asList(mLeAudioAllowList.split(",")); BluetoothProperties.le_audio_allow_list(leAudioAllowlistFromDeviceConfig); } } else { List<String> leAudioAllowDevices = Arrays.asList(mLeAudioAllowList.split(",")); BluetoothProperties.le_audio_allow_list(leAudioAllowDevices); mLeAudioAllowDevices = new HashSet<String>(leAudioAllowDevices); List<String> leAudioAllowlistProp = BluetoothProperties.le_audio_allow_list(); if (leAudioAllowlistProp != null && !leAudioAllowlistProp.isEmpty()) { mLeAudioAllowDevices.clear(); mLeAudioAllowDevices.addAll(leAudioAllowlistProp); } } } Loading Loading @@ -7735,56 +7731,22 @@ public class AdapterService extends Service { mNativeInterface.interopDatabaseAddRemoveName(false, feature.name(), name); } private void loadLeAudioAllowDevices() { Log.i(TAG, "loadLeAudioAllowDevices"); mLeAudioAllowListEnabled = SystemProperties.getBoolean(BLUETOOTH_ENABLE_LE_AUDIO_ALLOW_LIST, false); if (!mLeAudioAllowListEnabled) { Log.i(TAG, "LE Audio allow list is disabled."); return; } synchronized (mDeviceConfigLock) { mLeAudioAllowDevices = new HashSet<String>(Arrays.asList(mLeAudioAllowList.split(","))); } return; } /** * Checks the remote device is in the LE Audio allow list or not. * * @param device the device to check * @return boolean true if le audio allow list is not enabled or the device is in the allow * list, false otherwise. * @return boolean true if the device is in the allow list, false otherwise. */ public boolean isLeAudioAllowed(BluetoothDevice device) { if (!mLeAudioAllowListEnabled) { return true; } DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); if (deviceProp == null || deviceProp.getModelName() == null || !mLeAudioAllowDevices.contains(deviceProp.getModelName())) { if (mLeAudioService != null) { mLeAudioService.setConnectionPolicy( device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); } Log.e( TAG, String.format("Device %s not in the LE Audio allow list, ", device) + "force LE Audio policy to forbidden"); return false; } if (mLeAudioService != null) { mLeAudioService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); } return true; } Loading android/app/src/com/android/bluetooth/btservice/PhonePolicy.java +31 −18 Original line number Diff line number Diff line Loading @@ -73,10 +73,13 @@ public class PhonePolicy implements AdapterService.BluetoothStateCallback { @VisibleForTesting static final String AUTO_CONNECT_PROFILES_PROPERTY = "bluetooth.auto_connect_profiles.enabled"; private static final String CONFIG_LE_AUDIO_ENABLED_BY_DEFAULT = "le_audio_enabled_by_default"; private static boolean sLeAudioEnabledByDefault = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_BLUETOOTH, CONFIG_LE_AUDIO_ENABLED_BY_DEFAULT, false); private static final String LE_AUDIO_CONNECTION_BY_DEFAULT_PROPERTY = "ro.bluetooth.leaudio.le_audio_connection_by_default"; @VisibleForTesting static final String BYPASS_LE_AUDIO_ALLOWLIST_PROPERTY = "persist.bluetooth.leaudio.bypass_allow_list"; /** flag for multi auto connect */ public static boolean sIsHfpMultiAutoConnectEnabled = Loading @@ -97,6 +100,7 @@ public class PhonePolicy implements AdapterService.BluetoothStateCallback { private final HashSet<BluetoothDevice> mA2dpRetrySet = new HashSet<>(); private final HashSet<BluetoothDevice> mConnectOtherProfilesDeviceSet = new HashSet<>(); @VisibleForTesting boolean mAutoConnectProfilesSupported; @VisibleForTesting boolean mLeAudioEnabledByDefault; @Override public void onBluetoothStateChange(int prevState, int newState) { Loading Loading @@ -184,6 +188,8 @@ public class PhonePolicy implements AdapterService.BluetoothStateCallback { mHandler = new PhonePolicyHandler(service.getMainLooper()); mAutoConnectProfilesSupported = SystemProperties.getBoolean(AUTO_CONNECT_PROFILES_PROPERTY, false); mLeAudioEnabledByDefault = SystemProperties.getBoolean(LE_AUDIO_CONNECTION_BY_DEFAULT_PROPERTY, true); } // Policy implementation, all functions MUST be private Loading @@ -204,12 +210,24 @@ public class PhonePolicy implements AdapterService.BluetoothStateCallback { BassClientService bcService = mFactory.getBassClientService(); BatteryService batteryService = mFactory.getBatteryService(); boolean isLeAudioProfileAllowed = (leAudioService != null) final boolean isBypassLeAudioAllowlist = SystemProperties.getBoolean(BYPASS_LE_AUDIO_ALLOWLIST_PROPERTY, false); boolean isLeAudioProfileAllowed = (leAudioService != null) && Utils.arrayContains(uuids, BluetoothUuid.LE_AUDIO) && (leAudioService.getConnectionPolicy(device) != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) && mAdapterService.isLeAudioAllowed(device) && (sLeAudioEnabledByDefault || isDualModeAudioEnabled()); && (mLeAudioEnabledByDefault || isDualModeAudioEnabled()) && (isBypassLeAudioAllowlist || mAdapterService.isLeAudioAllowed(device)); debugLog( "mLeAudioEnabledByDefault: " + mLeAudioEnabledByDefault + ", isBypassLeAudioAllowlist: " + isBypassLeAudioAllowlist + ", isLeAudioAllowDevice: " + mAdapterService.isLeAudioAllowed(device)); // Set profile priorities only for the profiles discovered on the remote device. // This avoids needless auto-connect attempts to profiles non-existent on the remote device Loading Loading @@ -790,11 +808,11 @@ public class PhonePolicy implements AdapterService.BluetoothStateCallback { } if (leAudioService != null) { List<BluetoothDevice> leAudioConnDevList = leAudioService.getConnectedDevices(); if (!leAudioConnDevList.contains(device) && (leAudioService.getConnectionPolicy(device) if (!leAudioConnDevList.contains(device) && (leAudioService.getConnectionPolicy(device) == BluetoothProfile.CONNECTION_POLICY_ALLOWED) && (leAudioService.getConnectionState(device) == BluetoothProfile.STATE_DISCONNECTED) && mAdapterService.isLeAudioAllowed(device)) { == BluetoothProfile.STATE_DISCONNECTED)) { debugLog("Retrying connection to LEAudio with device " + device); leAudioService.connect(device); } Loading Loading @@ -866,11 +884,6 @@ public class PhonePolicy implements AdapterService.BluetoothStateCallback { } } @VisibleForTesting void setLeAudioEnabledByDefaultForTesting(boolean enabled) { sLeAudioEnabledByDefault = enabled; } private static void debugLog(String msg) { if (DBG) { Log.i(TAG, msg); Loading android/app/tests/unit/src/com/android/bluetooth/btservice/PhonePolicyTest.java +19 −12 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothUuid; import android.os.HandlerThread; import android.os.ParcelUuid; import android.os.SystemProperties; import androidx.room.Room; import androidx.test.filters.MediumTest; Loading Loading @@ -189,7 +190,7 @@ public class PhonePolicyTest { when(mAdapterService.isLeAudioAllowed(device)).thenReturn(true); // Auto connect to LE audio, HFP, A2DP processInitProfilePriorities_LeAudioHelper(true, true, false); processInitProfilePriorities_LeAudioHelper(true, true, false, false); verify(mLeAudioService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) .setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); verify(mA2dpService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) Loading @@ -198,7 +199,7 @@ public class PhonePolicyTest { .setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); // Does not auto connect and allow HFP and A2DP to be connected processInitProfilePriorities_LeAudioHelper(true, false, false); processInitProfilePriorities_LeAudioHelper(true, false, false, false); verify(mDatabaseManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) .setProfileConnectionPolicy(device, BluetoothProfile.LE_AUDIO, BluetoothProfile.CONNECTION_POLICY_ALLOWED); Loading @@ -209,8 +210,8 @@ public class PhonePolicyTest { .setProfileConnectionPolicy(device, BluetoothProfile.HEADSET, BluetoothProfile.CONNECTION_POLICY_ALLOWED); // Auto connect to LE audio but disallow HFP and A2DP processInitProfilePriorities_LeAudioHelper(false, true, false); // Auto connect to HFP and A2DP but disallow LE Audio processInitProfilePriorities_LeAudioHelper(false, true, false, false); verify(mDatabaseManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) .setProfileConnectionPolicy(device, BluetoothProfile.LE_AUDIO, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); Loading @@ -219,8 +220,8 @@ public class PhonePolicyTest { verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(2)) .setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); // Does not auto connect and disallow HFP and A2DP to be connected processInitProfilePriorities_LeAudioHelper(false, false, false); // Does not auto connect and disallow LE Audio to be connected processInitProfilePriorities_LeAudioHelper(false, false, false, false); verify(mDatabaseManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(2)) .setProfileConnectionPolicy(device, BluetoothProfile.LE_AUDIO, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); Loading @@ -238,7 +239,7 @@ public class PhonePolicyTest { when(mAdapterService.isLeAudioAllowed(device)).thenReturn(true); // Auto connect to LE audio, HFP, A2DP processInitProfilePriorities_LeAudioHelper(true, true, true); processInitProfilePriorities_LeAudioHelper(true, true, true, false); verify(mLeAudioService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) .setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); verify(mA2dpService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) Loading @@ -247,7 +248,7 @@ public class PhonePolicyTest { .setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); // Does not auto connect and allow HFP and A2DP to be connected processInitProfilePriorities_LeAudioHelper(true, false, true); processInitProfilePriorities_LeAudioHelper(true, false, true, false); verify(mDatabaseManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) .setProfileConnectionPolicy(device, BluetoothProfile.LE_AUDIO, BluetoothProfile.CONNECTION_POLICY_ALLOWED); Loading @@ -259,7 +260,7 @@ public class PhonePolicyTest { BluetoothProfile.CONNECTION_POLICY_ALLOWED); // Auto connect to LE audio but disallow HFP and A2DP processInitProfilePriorities_LeAudioHelper(false, true, true); processInitProfilePriorities_LeAudioHelper(false, true, true, false); verify(mLeAudioService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(2)) .setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); verify(mDatabaseManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) Loading @@ -270,7 +271,7 @@ public class PhonePolicyTest { BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); // Does not auto connect and disallow HFP and A2DP to be connected processInitProfilePriorities_LeAudioHelper(false, false, true); processInitProfilePriorities_LeAudioHelper(false, false, true, false); verify(mDatabaseManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(2)) .setProfileConnectionPolicy(device, BluetoothProfile.LE_AUDIO, BluetoothProfile.CONNECTION_POLICY_ALLOWED); Loading @@ -283,10 +284,16 @@ public class PhonePolicyTest { } private void processInitProfilePriorities_LeAudioHelper( boolean dualModeEnabled, boolean autoConnect, boolean leAudioEnabledByDefault) { boolean dualModeEnabled, boolean autoConnect, boolean leAudioEnabledByDefault, boolean bypassLeAudioAllowlist) { Utils.setDualModeAudioStateForTesting(dualModeEnabled); mPhonePolicy.setLeAudioEnabledByDefaultForTesting(leAudioEnabledByDefault); mPhonePolicy.mLeAudioEnabledByDefault = leAudioEnabledByDefault; mPhonePolicy.mAutoConnectProfilesSupported = autoConnect; SystemProperties.set( PhonePolicy.BYPASS_LE_AUDIO_ALLOWLIST_PROPERTY, Boolean.toString(bypassLeAudioAllowlist)); BluetoothDevice device = getTestDevice(mAdapter, 0); // Mock the HFP, A2DP and LE audio services to return unknown connection policy Loading Loading
android/app/src/com/android/bluetooth/btservice/AdapterService.java +13 −51 Original line number Diff line number Diff line Loading @@ -96,7 +96,6 @@ import android.os.PowerManager; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.provider.DeviceConfig; Loading Loading @@ -208,7 +207,6 @@ public class AdapterService extends Service { private final ArrayList<ProfileService> mRegisteredProfiles = new ArrayList<>(); private final ArrayList<ProfileService> mRunningProfiles = new ArrayList<>(); private HashSet<String> mLeAudioAllowDevices = new HashSet<>(); private boolean mLeAudioAllowListEnabled = false; public static final String ACTION_LOAD_ADAPTER_PROPERTIES = "com.android.bluetooth.btservice.action.LOAD_ADAPTER_PROPERTIES"; Loading Loading @@ -236,8 +234,7 @@ public class AdapterService extends Service { static final String LOCAL_MAC_ADDRESS_PERM = android.Manifest.permission.LOCAL_MAC_ADDRESS; static final String RECEIVE_MAP_PERM = android.Manifest.permission.RECEIVE_BLUETOOTH_MAP; static final String BLUETOOTH_LE_AUDIO_ALLOW_LIST = "persist.bluetooth.leaudio.allow_list"; static final String BLUETOOTH_ENABLE_LE_AUDIO_ALLOW_LIST = "persist.bluetooth.leaudio.enable_allow_list"; static final String PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE = "phonebook_access_permission"; static final String MESSAGE_ACCESS_PERMISSION_PREFERENCE_FILE = "message_access_permission"; Loading Loading @@ -673,7 +670,6 @@ public class AdapterService extends Service { mBluetoothQualityReportNativeInterface.init(); mSdpManager = SdpManager.init(this); loadLeAudioAllowDevices(); mDatabaseManager = new DatabaseManager(this); mDatabaseManager.start(MetadataDatabase.createDatabase(this)); Loading Loading @@ -1554,8 +1550,7 @@ public class AdapterService extends Service { return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.COORDINATED_SET); } if (profile == BluetoothProfile.LE_AUDIO) { return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.LE_AUDIO) && isLeAudioAllowed(device); return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.LE_AUDIO); } if (profile == BluetoothProfile.HAP_CLIENT) { return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HAS); Loading Loading @@ -7503,15 +7498,16 @@ public class AdapterService extends Service { ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_INTERVAL_MS); mLeAudioAllowList = properties.getString(LE_AUDIO_ALLOW_LIST, ""); if (mLeAudioAllowList.isEmpty()) { List<String> leAudioAllowDevices = BluetoothProperties.le_audio_allow_list(); if (leAudioAllowDevices != null && !leAudioAllowDevices.isEmpty()) { mLeAudioAllowDevices = new HashSet<String>(leAudioAllowDevices); if (!mLeAudioAllowList.isEmpty()) { List<String> leAudioAllowlistFromDeviceConfig = Arrays.asList(mLeAudioAllowList.split(",")); BluetoothProperties.le_audio_allow_list(leAudioAllowlistFromDeviceConfig); } } else { List<String> leAudioAllowDevices = Arrays.asList(mLeAudioAllowList.split(",")); BluetoothProperties.le_audio_allow_list(leAudioAllowDevices); mLeAudioAllowDevices = new HashSet<String>(leAudioAllowDevices); List<String> leAudioAllowlistProp = BluetoothProperties.le_audio_allow_list(); if (leAudioAllowlistProp != null && !leAudioAllowlistProp.isEmpty()) { mLeAudioAllowDevices.clear(); mLeAudioAllowDevices.addAll(leAudioAllowlistProp); } } } Loading Loading @@ -7735,56 +7731,22 @@ public class AdapterService extends Service { mNativeInterface.interopDatabaseAddRemoveName(false, feature.name(), name); } private void loadLeAudioAllowDevices() { Log.i(TAG, "loadLeAudioAllowDevices"); mLeAudioAllowListEnabled = SystemProperties.getBoolean(BLUETOOTH_ENABLE_LE_AUDIO_ALLOW_LIST, false); if (!mLeAudioAllowListEnabled) { Log.i(TAG, "LE Audio allow list is disabled."); return; } synchronized (mDeviceConfigLock) { mLeAudioAllowDevices = new HashSet<String>(Arrays.asList(mLeAudioAllowList.split(","))); } return; } /** * Checks the remote device is in the LE Audio allow list or not. * * @param device the device to check * @return boolean true if le audio allow list is not enabled or the device is in the allow * list, false otherwise. * @return boolean true if the device is in the allow list, false otherwise. */ public boolean isLeAudioAllowed(BluetoothDevice device) { if (!mLeAudioAllowListEnabled) { return true; } DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); if (deviceProp == null || deviceProp.getModelName() == null || !mLeAudioAllowDevices.contains(deviceProp.getModelName())) { if (mLeAudioService != null) { mLeAudioService.setConnectionPolicy( device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); } Log.e( TAG, String.format("Device %s not in the LE Audio allow list, ", device) + "force LE Audio policy to forbidden"); return false; } if (mLeAudioService != null) { mLeAudioService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); } return true; } Loading
android/app/src/com/android/bluetooth/btservice/PhonePolicy.java +31 −18 Original line number Diff line number Diff line Loading @@ -73,10 +73,13 @@ public class PhonePolicy implements AdapterService.BluetoothStateCallback { @VisibleForTesting static final String AUTO_CONNECT_PROFILES_PROPERTY = "bluetooth.auto_connect_profiles.enabled"; private static final String CONFIG_LE_AUDIO_ENABLED_BY_DEFAULT = "le_audio_enabled_by_default"; private static boolean sLeAudioEnabledByDefault = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_BLUETOOTH, CONFIG_LE_AUDIO_ENABLED_BY_DEFAULT, false); private static final String LE_AUDIO_CONNECTION_BY_DEFAULT_PROPERTY = "ro.bluetooth.leaudio.le_audio_connection_by_default"; @VisibleForTesting static final String BYPASS_LE_AUDIO_ALLOWLIST_PROPERTY = "persist.bluetooth.leaudio.bypass_allow_list"; /** flag for multi auto connect */ public static boolean sIsHfpMultiAutoConnectEnabled = Loading @@ -97,6 +100,7 @@ public class PhonePolicy implements AdapterService.BluetoothStateCallback { private final HashSet<BluetoothDevice> mA2dpRetrySet = new HashSet<>(); private final HashSet<BluetoothDevice> mConnectOtherProfilesDeviceSet = new HashSet<>(); @VisibleForTesting boolean mAutoConnectProfilesSupported; @VisibleForTesting boolean mLeAudioEnabledByDefault; @Override public void onBluetoothStateChange(int prevState, int newState) { Loading Loading @@ -184,6 +188,8 @@ public class PhonePolicy implements AdapterService.BluetoothStateCallback { mHandler = new PhonePolicyHandler(service.getMainLooper()); mAutoConnectProfilesSupported = SystemProperties.getBoolean(AUTO_CONNECT_PROFILES_PROPERTY, false); mLeAudioEnabledByDefault = SystemProperties.getBoolean(LE_AUDIO_CONNECTION_BY_DEFAULT_PROPERTY, true); } // Policy implementation, all functions MUST be private Loading @@ -204,12 +210,24 @@ public class PhonePolicy implements AdapterService.BluetoothStateCallback { BassClientService bcService = mFactory.getBassClientService(); BatteryService batteryService = mFactory.getBatteryService(); boolean isLeAudioProfileAllowed = (leAudioService != null) final boolean isBypassLeAudioAllowlist = SystemProperties.getBoolean(BYPASS_LE_AUDIO_ALLOWLIST_PROPERTY, false); boolean isLeAudioProfileAllowed = (leAudioService != null) && Utils.arrayContains(uuids, BluetoothUuid.LE_AUDIO) && (leAudioService.getConnectionPolicy(device) != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) && mAdapterService.isLeAudioAllowed(device) && (sLeAudioEnabledByDefault || isDualModeAudioEnabled()); && (mLeAudioEnabledByDefault || isDualModeAudioEnabled()) && (isBypassLeAudioAllowlist || mAdapterService.isLeAudioAllowed(device)); debugLog( "mLeAudioEnabledByDefault: " + mLeAudioEnabledByDefault + ", isBypassLeAudioAllowlist: " + isBypassLeAudioAllowlist + ", isLeAudioAllowDevice: " + mAdapterService.isLeAudioAllowed(device)); // Set profile priorities only for the profiles discovered on the remote device. // This avoids needless auto-connect attempts to profiles non-existent on the remote device Loading Loading @@ -790,11 +808,11 @@ public class PhonePolicy implements AdapterService.BluetoothStateCallback { } if (leAudioService != null) { List<BluetoothDevice> leAudioConnDevList = leAudioService.getConnectedDevices(); if (!leAudioConnDevList.contains(device) && (leAudioService.getConnectionPolicy(device) if (!leAudioConnDevList.contains(device) && (leAudioService.getConnectionPolicy(device) == BluetoothProfile.CONNECTION_POLICY_ALLOWED) && (leAudioService.getConnectionState(device) == BluetoothProfile.STATE_DISCONNECTED) && mAdapterService.isLeAudioAllowed(device)) { == BluetoothProfile.STATE_DISCONNECTED)) { debugLog("Retrying connection to LEAudio with device " + device); leAudioService.connect(device); } Loading Loading @@ -866,11 +884,6 @@ public class PhonePolicy implements AdapterService.BluetoothStateCallback { } } @VisibleForTesting void setLeAudioEnabledByDefaultForTesting(boolean enabled) { sLeAudioEnabledByDefault = enabled; } private static void debugLog(String msg) { if (DBG) { Log.i(TAG, msg); Loading
android/app/tests/unit/src/com/android/bluetooth/btservice/PhonePolicyTest.java +19 −12 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothUuid; import android.os.HandlerThread; import android.os.ParcelUuid; import android.os.SystemProperties; import androidx.room.Room; import androidx.test.filters.MediumTest; Loading Loading @@ -189,7 +190,7 @@ public class PhonePolicyTest { when(mAdapterService.isLeAudioAllowed(device)).thenReturn(true); // Auto connect to LE audio, HFP, A2DP processInitProfilePriorities_LeAudioHelper(true, true, false); processInitProfilePriorities_LeAudioHelper(true, true, false, false); verify(mLeAudioService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) .setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); verify(mA2dpService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) Loading @@ -198,7 +199,7 @@ public class PhonePolicyTest { .setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); // Does not auto connect and allow HFP and A2DP to be connected processInitProfilePriorities_LeAudioHelper(true, false, false); processInitProfilePriorities_LeAudioHelper(true, false, false, false); verify(mDatabaseManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) .setProfileConnectionPolicy(device, BluetoothProfile.LE_AUDIO, BluetoothProfile.CONNECTION_POLICY_ALLOWED); Loading @@ -209,8 +210,8 @@ public class PhonePolicyTest { .setProfileConnectionPolicy(device, BluetoothProfile.HEADSET, BluetoothProfile.CONNECTION_POLICY_ALLOWED); // Auto connect to LE audio but disallow HFP and A2DP processInitProfilePriorities_LeAudioHelper(false, true, false); // Auto connect to HFP and A2DP but disallow LE Audio processInitProfilePriorities_LeAudioHelper(false, true, false, false); verify(mDatabaseManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) .setProfileConnectionPolicy(device, BluetoothProfile.LE_AUDIO, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); Loading @@ -219,8 +220,8 @@ public class PhonePolicyTest { verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(2)) .setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); // Does not auto connect and disallow HFP and A2DP to be connected processInitProfilePriorities_LeAudioHelper(false, false, false); // Does not auto connect and disallow LE Audio to be connected processInitProfilePriorities_LeAudioHelper(false, false, false, false); verify(mDatabaseManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(2)) .setProfileConnectionPolicy(device, BluetoothProfile.LE_AUDIO, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); Loading @@ -238,7 +239,7 @@ public class PhonePolicyTest { when(mAdapterService.isLeAudioAllowed(device)).thenReturn(true); // Auto connect to LE audio, HFP, A2DP processInitProfilePriorities_LeAudioHelper(true, true, true); processInitProfilePriorities_LeAudioHelper(true, true, true, false); verify(mLeAudioService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) .setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); verify(mA2dpService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) Loading @@ -247,7 +248,7 @@ public class PhonePolicyTest { .setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); // Does not auto connect and allow HFP and A2DP to be connected processInitProfilePriorities_LeAudioHelper(true, false, true); processInitProfilePriorities_LeAudioHelper(true, false, true, false); verify(mDatabaseManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) .setProfileConnectionPolicy(device, BluetoothProfile.LE_AUDIO, BluetoothProfile.CONNECTION_POLICY_ALLOWED); Loading @@ -259,7 +260,7 @@ public class PhonePolicyTest { BluetoothProfile.CONNECTION_POLICY_ALLOWED); // Auto connect to LE audio but disallow HFP and A2DP processInitProfilePriorities_LeAudioHelper(false, true, true); processInitProfilePriorities_LeAudioHelper(false, true, true, false); verify(mLeAudioService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(2)) .setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); verify(mDatabaseManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) Loading @@ -270,7 +271,7 @@ public class PhonePolicyTest { BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); // Does not auto connect and disallow HFP and A2DP to be connected processInitProfilePriorities_LeAudioHelper(false, false, true); processInitProfilePriorities_LeAudioHelper(false, false, true, false); verify(mDatabaseManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(2)) .setProfileConnectionPolicy(device, BluetoothProfile.LE_AUDIO, BluetoothProfile.CONNECTION_POLICY_ALLOWED); Loading @@ -283,10 +284,16 @@ public class PhonePolicyTest { } private void processInitProfilePriorities_LeAudioHelper( boolean dualModeEnabled, boolean autoConnect, boolean leAudioEnabledByDefault) { boolean dualModeEnabled, boolean autoConnect, boolean leAudioEnabledByDefault, boolean bypassLeAudioAllowlist) { Utils.setDualModeAudioStateForTesting(dualModeEnabled); mPhonePolicy.setLeAudioEnabledByDefaultForTesting(leAudioEnabledByDefault); mPhonePolicy.mLeAudioEnabledByDefault = leAudioEnabledByDefault; mPhonePolicy.mAutoConnectProfilesSupported = autoConnect; SystemProperties.set( PhonePolicy.BYPASS_LE_AUDIO_ALLOWLIST_PROPERTY, Boolean.toString(bypassLeAudioAllowlist)); BluetoothDevice device = getTestDevice(mAdapter, 0); // Mock the HFP, A2DP and LE audio services to return unknown connection policy Loading