Loading android/app/src/com/android/bluetooth/btservice/AbstractionLayer.java +1 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ public final class AbstractionLayer { static final int BT_PROPERTY_WL_MEDIA_PLAYERS_LIST = 0x14; static final int BT_PROPERTY_REMOTE_ASHA_CAPABILITY = 0X15; static final int BT_PROPERTY_REMOTE_ASHA_TRUNCATED_HISYNCID = 0X16; static final int BT_PROPERTY_REMOTE_MODEL_NUM = 0x17; public static final int BT_DEVICE_TYPE_BREDR = 0x01; public static final int BT_DEVICE_TYPE_BLE = 0x02; Loading android/app/src/com/android/bluetooth/btservice/AdapterService.java +76 −1 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ 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 @@ -189,6 +190,8 @@ public class AdapterService extends Service { private final ArrayList<String> mStartedProfiles = new ArrayList<>(); 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 @@ -218,6 +221,9 @@ public class AdapterService extends Service { static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 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"; private static final String PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE = "phonebook_access_permission"; Loading Loading @@ -559,6 +565,7 @@ public class AdapterService extends Service { mSdpManager = SdpManager.init(this); registerReceiver(mAlarmBroadcastReceiver, new IntentFilter(ACTION_ALARM_WAKEUP)); loadLeAudioAllowDevices(); mDatabaseManager = new DatabaseManager(this); mDatabaseManager.start(MetadataDatabase.createDatabase(this)); Loading Loading @@ -1268,7 +1275,8 @@ public class AdapterService extends Service { return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.COORDINATED_SET); } if (profile == BluetoothProfile.LE_AUDIO) { return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.LE_AUDIO); return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.LE_AUDIO) && isLeAudioAllowed(device); } if (profile == BluetoothProfile.HAP_CLIENT) { return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HAS); Loading Loading @@ -6229,6 +6237,8 @@ public class AdapterService extends Service { @GuardedBy("mDeviceConfigLock") private int mScreenOffBalancedIntervalMillis = ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_INTERVAL_MS; @GuardedBy("mDeviceConfigLock") private String mLeAudioAllowList; public @NonNull Predicate<String> getLocationDenylistName() { synchronized (mDeviceConfigLock) { Loading Loading @@ -6356,6 +6366,8 @@ public class AdapterService extends Service { "screen_off_balanced_window_millis"; private static final String SCREEN_OFF_BALANCED_INTERVAL_MILLIS = "screen_off_balanced_interval_millis"; private static final String LE_AUDIO_ALLOW_LIST = "le_audio_allow_list"; /** * Default denylist which matches Eddystone and iBeacon payloads. Loading Loading @@ -6411,6 +6423,18 @@ public class AdapterService extends Service { mScreenOffBalancedIntervalMillis = properties.getInt( SCREEN_OFF_BALANCED_INTERVAL_MILLIS, 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); } } else { List<String> leAudioAllowDevices = Arrays.asList(mLeAudioAllowList.split(",")); BluetoothProperties.le_audio_allow_list(leAudioAllowDevices); mLeAudioAllowDevices = new HashSet<String>(leAudioAllowDevices); } } } } Loading Loading @@ -6620,6 +6644,57 @@ public class AdapterService extends Service { interopDatabaseAddRemoveNameNative(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. */ 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; } static native void classInitNative(); native boolean initNative(boolean startRestricted, boolean isCommonCriteriaMode, Loading android/app/src/com/android/bluetooth/btservice/PhonePolicy.java +4 −2 Original line number Diff line number Diff line Loading @@ -358,7 +358,8 @@ class PhonePolicy { boolean isLeAudioProfileAllowed = false; if ((leAudioService != null) && Utils.arrayContains(uuids, BluetoothUuid.LE_AUDIO) && (leAudioService.getConnectionPolicy(device) != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)) { != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) && mAdapterService.isLeAudioAllowed(device)) { debugLog("setting le audio profile priority for device " + device); isLeAudioProfileAllowed = true; if (leAudioService.getConnectionPolicy(device) Loading Loading @@ -725,7 +726,8 @@ class PhonePolicy { if (!leAudioConnDevList.contains(device) && (leAudioService.getConnectionPolicy(device) == BluetoothProfile.CONNECTION_POLICY_ALLOWED) && (leAudioService.getConnectionState(device) == BluetoothProfile.STATE_DISCONNECTED)) { == BluetoothProfile.STATE_DISCONNECTED) && mAdapterService.isLeAudioAllowed(device)) { debugLog("Retrying connection to LEAudio with device " + device); leAudioService.connect(device); } Loading android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +19 −0 Original line number Diff line number Diff line Loading @@ -317,6 +317,7 @@ final class RemoteDevices { private boolean mIsCoordinatedSetMember; private int mAshaCapability; private int mAshaTruncatedHiSyncId; private String mModelName; @VisibleForTesting int mBondState; @VisibleForTesting int mDeviceType; @VisibleForTesting ParcelUuid[] mUuids; Loading Loading @@ -672,6 +673,19 @@ final class RemoteDevices { public BluetoothSinkAudioPolicy getHfAudioPolicyForRemoteAg() { return mAudioPolicy; } public void setModelName(String modelName) { mModelName = modelName; } /** * @return the mModelName */ String getModelName() { synchronized (mObject) { return mModelName; } } } private void sendUuidIntent(BluetoothDevice device, DeviceProperties prop) { Loading Loading @@ -917,6 +931,11 @@ final class RemoteDevices { case AbstractionLayer.BT_PROPERTY_REMOTE_ASHA_TRUNCATED_HISYNCID: deviceProperties.setAshaTruncatedHiSyncId(val[0]); break; case AbstractionLayer.BT_PROPERTY_REMOTE_MODEL_NUM: final String modelName = new String(val); debugLog("Remote device model name: " + modelName); deviceProperties.setModelName(modelName); break; } } } Loading system/bta/csis/csis_types.h +6 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include "bta_csis_api.h" #include "bta_gatt_api.h" #include "bta_groups.h" #include "btif_storage.h" #include "gap_api.h" #include "gd/common/init_flags.h" #include "gd/common/strings.h" Loading Loading @@ -291,8 +292,13 @@ class CsisGroup { target_lock_state_(CsisLockState::CSIS_STATE_UNSET), lock_transition_cnt_(0) { devices_.clear(); BTIF_STORAGE_FILL_PROPERTY(&model_name, BT_PROPERTY_REMOTE_MODEL_NUM, sizeof(model_name_val), &model_name_val); } bt_property_t model_name; bt_bdname_t model_name_val = {0}; void AddDevice(std::shared_ptr<CsisDevice> csis_device) { auto it = find_if(devices_.begin(), devices_.end(), CsisDevice::MatchAddress(csis_device->addr)); Loading Loading
android/app/src/com/android/bluetooth/btservice/AbstractionLayer.java +1 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ public final class AbstractionLayer { static final int BT_PROPERTY_WL_MEDIA_PLAYERS_LIST = 0x14; static final int BT_PROPERTY_REMOTE_ASHA_CAPABILITY = 0X15; static final int BT_PROPERTY_REMOTE_ASHA_TRUNCATED_HISYNCID = 0X16; static final int BT_PROPERTY_REMOTE_MODEL_NUM = 0x17; public static final int BT_DEVICE_TYPE_BREDR = 0x01; public static final int BT_DEVICE_TYPE_BLE = 0x02; Loading
android/app/src/com/android/bluetooth/btservice/AdapterService.java +76 −1 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ 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 @@ -189,6 +190,8 @@ public class AdapterService extends Service { private final ArrayList<String> mStartedProfiles = new ArrayList<>(); 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 @@ -218,6 +221,9 @@ public class AdapterService extends Service { static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 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"; private static final String PHONEBOOK_ACCESS_PERMISSION_PREFERENCE_FILE = "phonebook_access_permission"; Loading Loading @@ -559,6 +565,7 @@ public class AdapterService extends Service { mSdpManager = SdpManager.init(this); registerReceiver(mAlarmBroadcastReceiver, new IntentFilter(ACTION_ALARM_WAKEUP)); loadLeAudioAllowDevices(); mDatabaseManager = new DatabaseManager(this); mDatabaseManager.start(MetadataDatabase.createDatabase(this)); Loading Loading @@ -1268,7 +1275,8 @@ public class AdapterService extends Service { return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.COORDINATED_SET); } if (profile == BluetoothProfile.LE_AUDIO) { return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.LE_AUDIO); return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.LE_AUDIO) && isLeAudioAllowed(device); } if (profile == BluetoothProfile.HAP_CLIENT) { return Utils.arrayContains(remoteDeviceUuids, BluetoothUuid.HAS); Loading Loading @@ -6229,6 +6237,8 @@ public class AdapterService extends Service { @GuardedBy("mDeviceConfigLock") private int mScreenOffBalancedIntervalMillis = ScanManager.SCAN_MODE_SCREEN_OFF_BALANCED_INTERVAL_MS; @GuardedBy("mDeviceConfigLock") private String mLeAudioAllowList; public @NonNull Predicate<String> getLocationDenylistName() { synchronized (mDeviceConfigLock) { Loading Loading @@ -6356,6 +6366,8 @@ public class AdapterService extends Service { "screen_off_balanced_window_millis"; private static final String SCREEN_OFF_BALANCED_INTERVAL_MILLIS = "screen_off_balanced_interval_millis"; private static final String LE_AUDIO_ALLOW_LIST = "le_audio_allow_list"; /** * Default denylist which matches Eddystone and iBeacon payloads. Loading Loading @@ -6411,6 +6423,18 @@ public class AdapterService extends Service { mScreenOffBalancedIntervalMillis = properties.getInt( SCREEN_OFF_BALANCED_INTERVAL_MILLIS, 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); } } else { List<String> leAudioAllowDevices = Arrays.asList(mLeAudioAllowList.split(",")); BluetoothProperties.le_audio_allow_list(leAudioAllowDevices); mLeAudioAllowDevices = new HashSet<String>(leAudioAllowDevices); } } } } Loading Loading @@ -6620,6 +6644,57 @@ public class AdapterService extends Service { interopDatabaseAddRemoveNameNative(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. */ 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; } static native void classInitNative(); native boolean initNative(boolean startRestricted, boolean isCommonCriteriaMode, Loading
android/app/src/com/android/bluetooth/btservice/PhonePolicy.java +4 −2 Original line number Diff line number Diff line Loading @@ -358,7 +358,8 @@ class PhonePolicy { boolean isLeAudioProfileAllowed = false; if ((leAudioService != null) && Utils.arrayContains(uuids, BluetoothUuid.LE_AUDIO) && (leAudioService.getConnectionPolicy(device) != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)) { != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) && mAdapterService.isLeAudioAllowed(device)) { debugLog("setting le audio profile priority for device " + device); isLeAudioProfileAllowed = true; if (leAudioService.getConnectionPolicy(device) Loading Loading @@ -725,7 +726,8 @@ class PhonePolicy { if (!leAudioConnDevList.contains(device) && (leAudioService.getConnectionPolicy(device) == BluetoothProfile.CONNECTION_POLICY_ALLOWED) && (leAudioService.getConnectionState(device) == BluetoothProfile.STATE_DISCONNECTED)) { == BluetoothProfile.STATE_DISCONNECTED) && mAdapterService.isLeAudioAllowed(device)) { debugLog("Retrying connection to LEAudio with device " + device); leAudioService.connect(device); } Loading
android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +19 −0 Original line number Diff line number Diff line Loading @@ -317,6 +317,7 @@ final class RemoteDevices { private boolean mIsCoordinatedSetMember; private int mAshaCapability; private int mAshaTruncatedHiSyncId; private String mModelName; @VisibleForTesting int mBondState; @VisibleForTesting int mDeviceType; @VisibleForTesting ParcelUuid[] mUuids; Loading Loading @@ -672,6 +673,19 @@ final class RemoteDevices { public BluetoothSinkAudioPolicy getHfAudioPolicyForRemoteAg() { return mAudioPolicy; } public void setModelName(String modelName) { mModelName = modelName; } /** * @return the mModelName */ String getModelName() { synchronized (mObject) { return mModelName; } } } private void sendUuidIntent(BluetoothDevice device, DeviceProperties prop) { Loading Loading @@ -917,6 +931,11 @@ final class RemoteDevices { case AbstractionLayer.BT_PROPERTY_REMOTE_ASHA_TRUNCATED_HISYNCID: deviceProperties.setAshaTruncatedHiSyncId(val[0]); break; case AbstractionLayer.BT_PROPERTY_REMOTE_MODEL_NUM: final String modelName = new String(val); debugLog("Remote device model name: " + modelName); deviceProperties.setModelName(modelName); break; } } } Loading
system/bta/csis/csis_types.h +6 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include "bta_csis_api.h" #include "bta_gatt_api.h" #include "bta_groups.h" #include "btif_storage.h" #include "gap_api.h" #include "gd/common/init_flags.h" #include "gd/common/strings.h" Loading Loading @@ -291,8 +292,13 @@ class CsisGroup { target_lock_state_(CsisLockState::CSIS_STATE_UNSET), lock_transition_cnt_(0) { devices_.clear(); BTIF_STORAGE_FILL_PROPERTY(&model_name, BT_PROPERTY_REMOTE_MODEL_NUM, sizeof(model_name_val), &model_name_val); } bt_property_t model_name; bt_bdname_t model_name_val = {0}; void AddDevice(std::shared_ptr<CsisDevice> csis_device) { auto it = find_if(devices_.begin(), devices_.end(), CsisDevice::MatchAddress(csis_device->addr)); Loading