Loading android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +73 −48 Original line number Diff line number Diff line Loading @@ -182,10 +182,8 @@ public class LeAudioService extends ProfileService { private BroadcastReceiver mMuteStateChangedReceiver; private int mStoredRingerMode = -1; private Handler mHandler = new Handler(Looper.getMainLooper()); private final AudioManagerAddAudioDeviceCallback mAudioManagerAddAudioDeviceCallback = new AudioManagerAddAudioDeviceCallback(); private final AudioManagerRemoveAudioDeviceCallback mAudioManagerRemoveAudioDeviceCallback = new AudioManagerRemoveAudioDeviceCallback(); private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback = new AudioManagerAudioDeviceCallback(); private final Map<Integer, Integer> mBroadcastStateMap = new HashMap<>(); private final Map<Integer, Boolean> mBroadcastsPlaybackMap = new HashMap<>(); Loading Loading @@ -281,6 +279,9 @@ public class LeAudioService extends ProfileService { mTmapGattServer = LeAudioObjectsFactory.getInstance().getTmapGattServer(this); mTmapGattServer.start(tmapRoleMask); mAudioManager.registerAudioDeviceCallback(mAudioManagerAudioDeviceCallback, mHandler); // Mark service as started setLeAudioService(this); Loading Loading @@ -399,8 +400,7 @@ public class LeAudioService extends ProfileService { } } mAudioManager.unregisterAudioDeviceCallback(mAudioManagerAddAudioDeviceCallback); mAudioManager.unregisterAudioDeviceCallback(mAudioManagerRemoveAudioDeviceCallback); mAudioManager.unregisterAudioDeviceCallback(mAudioManagerAudioDeviceCallback); mAdapterService = null; mAudioManager = null; Loading Loading @@ -995,54 +995,85 @@ public class LeAudioService extends ProfileService { * is added or removed. */ @VisibleForTesting void notifyActiveDeviceChanged() { void notifyActiveDeviceChanged(BluetoothDevice device) { if (DBG) { Log.d(TAG, "Notify Active device changed." + device + ". Currently active device is " + mActiveAudioOutDevice); } Intent intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mActiveAudioOutDevice != null ? mActiveAudioOutDevice : mActiveAudioInDevice); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); sendBroadcast(intent, BLUETOOTH_CONNECT); } /* Notifications of audio device disconnection events. */ private class AudioManagerRemoveAudioDeviceCallback extends AudioDeviceCallback { /* Notifications of audio device connection/disconn events. */ private class AudioManagerAudioDeviceCallback extends AudioDeviceCallback { @Override public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) { if (mAudioManager == null) { public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) { if (mAudioManager == null || mAdapterService == null) { Log.e(TAG, "Callback called when LeAudioService is stopped"); return; } for (AudioDeviceInfo deviceInfo : removedDevices) { if (deviceInfo.getType() == AudioDeviceInfo.TYPE_BLE_HEADSET || deviceInfo.getType() == AudioDeviceInfo.TYPE_BLE_SPEAKER) { notifyActiveDeviceChanged(); if (DBG) { Log.d(TAG, " onAudioDevicesRemoved: device type: " + deviceInfo.getType()); for (AudioDeviceInfo deviceInfo : addedDevices) { if ((deviceInfo.getType() != AudioDeviceInfo.TYPE_BLE_HEADSET) && (deviceInfo.getType() != AudioDeviceInfo.TYPE_BLE_SPEAKER)) { continue; } mAudioManager.unregisterAudioDeviceCallback(this); String address = deviceInfo.getAddress(); if (address.equals("00:00:00:00:00:00")) { continue; } byte[] addressBytes = Utils.getBytesFromAddress(address); BluetoothDevice device = mAdapterService.getDeviceFromByte(addressBytes); if (DBG) { Log.d(TAG, " onAudioDevicesAdded: " + device + ", device type: " + deviceInfo.getType() + ", isSink: " + deviceInfo.isSink() + " isSource: " + deviceInfo.isSource()); } if ((deviceInfo.isSink() && !device.equals(mActiveAudioOutDevice)) || (deviceInfo.isSource() && !device.equals(mActiveAudioInDevice))) { Log.e(TAG, "Added device does not match to the one activated here. (" + device + " != " + mActiveAudioOutDevice + " / " + mActiveAudioInDevice + ")"); continue; } notifyActiveDeviceChanged(device); return; } } /* Notifications of audio device connection events. */ private class AudioManagerAddAudioDeviceCallback extends AudioDeviceCallback { @Override public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) { if (mAudioManager == null) { public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) { if (mAudioManager == null || mAdapterService == null) { Log.e(TAG, "Callback called when LeAudioService is stopped"); return; } for (AudioDeviceInfo deviceInfo : addedDevices) { if (deviceInfo.getType() == AudioDeviceInfo.TYPE_BLE_HEADSET || deviceInfo.getType() == AudioDeviceInfo.TYPE_BLE_SPEAKER) { notifyActiveDeviceChanged(); if (DBG) { Log.d(TAG, " onAudioDevicesAdded: device type: " + deviceInfo.getType()); for (AudioDeviceInfo deviceInfo : removedDevices) { if ((deviceInfo.getType() != AudioDeviceInfo.TYPE_BLE_HEADSET) && (deviceInfo.getType() != AudioDeviceInfo.TYPE_BLE_SPEAKER)) { continue; } mAudioManager.unregisterAudioDeviceCallback(this); String address = deviceInfo.getAddress(); if (address.equals("00:00:00:00:00:00")) { continue; } if (DBG) { Log.d(TAG, " onAudioDevicesRemoved: " + address + ", device type: " + deviceInfo.getType() + ", isSink: " + deviceInfo.isSink() + " isSource: " + deviceInfo.isSource() + ", mActiveAudioInDevice: " + mActiveAudioInDevice + ", mActiveAudioOutDevice: " + mActiveAudioOutDevice); } } } Loading Loading @@ -1077,20 +1108,6 @@ public class LeAudioService extends ProfileService { + ", " + mActiveAudioInDevice); } /* Active device changed, there is need to inform about new active LE Audio device */ if (isNewActiveOutDevice || isNewActiveInDevice) { /* Register for new device connection/disconnection in Audio Manager */ if (mActiveAudioOutDevice != null || mActiveAudioInDevice != null) { /* Register for any device connection in case if any of devices become connected */ mAudioManager.registerAudioDeviceCallback(mAudioManagerAddAudioDeviceCallback, mHandler); } else { /* Register for disconnection if active devices become non-active */ mAudioManager.registerAudioDeviceCallback(mAudioManagerRemoveAudioDeviceCallback, mHandler); } } if (isNewActiveOutDevice) { int volume = IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME; Loading @@ -1112,6 +1129,14 @@ public class LeAudioService extends ProfileService { false)); } if ((mActiveAudioOutDevice == null) && (mActiveAudioInDevice == null)) { /* Notify about inactive device as soon as possible. * When adding new device, wait with notification until AudioManager is ready * with adding the device. */ notifyActiveDeviceChanged(null); } return mActiveAudioOutDevice != null; } Loading android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java +3 −3 Original line number Diff line number Diff line Loading @@ -1147,7 +1147,7 @@ public class LeAudioServiceTest { /* Since LeAudioService called AudioManager - assume Audio manager calles properly callback * mAudioManager.onAudioDeviceAdded */ mService.notifyActiveDeviceChanged(); mService.notifyActiveDeviceChanged(mSingleDevice); String action = BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED; Intent intent = TestUtils.waitForIntent(TIMEOUT_MS, mDeviceQueueMap.get(mSingleDevice)); Loading Loading @@ -1363,7 +1363,7 @@ public class LeAudioServiceTest { /* Since LeAudioService called AudioManager - assume Audio manager calles properly callback * mAudioManager.onAudioDeviceAdded */ mService.notifyActiveDeviceChanged(); mService.notifyActiveDeviceChanged(leadDevice); doReturn(BluetoothDevice.BOND_BONDED).when(mAdapterService).getBondState(leadDevice); verifyActiveDeviceStateIntent(AUDIO_MANAGER_DEVICE_ADD_TIMEOUT_MS, leadDevice); injectNoVerifyDeviceDisconnected(leadDevice); Loading Loading @@ -1432,7 +1432,7 @@ public class LeAudioServiceTest { /* Since LeAudioService called AudioManager - assume Audio manager calles properly callback * mAudioManager.onAudioDeviceAdded */ mService.notifyActiveDeviceChanged(); mService.notifyActiveDeviceChanged(leadDevice); verifyActiveDeviceStateIntent(AUDIO_MANAGER_DEVICE_ADD_TIMEOUT_MS, leadDevice); /* We don't want to distribute DISCONNECTION event, instead will try to reconnect Loading android/pandora/mmi2grpc/mmi2grpc/gap.py +1 −1 Original line number Diff line number Diff line Loading @@ -207,7 +207,7 @@ class GAPProxy(ProfileProxy): self.host.StartAdvertising( own_address_type=OwnAddressType.PUBLIC, data=DataTypes(incomplete_service_class_uuids128=["955798ce-3022-455c-b759-ee8edcd73d1a"],)) data=DataTypes(complete_service_class_uuids128=["955798ce-3022-455c-b759-ee8edcd73d1a"],)) return "OK" @assert_description Loading android/pandora/server/src/com/android/pandora/Host.kt +23 −15 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ import android.bluetooth.BluetoothDevice.TRANSPORT_BREDR import android.bluetooth.BluetoothDevice.TRANSPORT_LE import android.bluetooth.BluetoothManager import android.bluetooth.BluetoothProfile import android.bluetooth.BluetoothUuid; import android.bluetooth.BluetoothUuid import android.bluetooth.le.AdvertiseCallback import android.bluetooth.le.AdvertiseData import android.bluetooth.le.AdvertiseSettings Loading Loading @@ -550,21 +550,23 @@ class Host( val dataTypesRequest = request.data if ( !dataTypesRequest.getCompleteServiceClassUuids16List().isEmpty() or !dataTypesRequest.getCompleteServiceClassUuids32List().isEmpty() or !dataTypesRequest.getCompleteServiceClassUuids128List().isEmpty() !dataTypesRequest.getIncompleteServiceClassUuids16List().isEmpty() or !dataTypesRequest.getIncompleteServiceClassUuids32List().isEmpty() or !dataTypesRequest.getIncompleteServiceClassUuids128List().isEmpty() ) { Log.e(TAG, "Complete Service Class Uuids not supported") Log.e(TAG, "Incomplete Service Class Uuids not supported") throw Status.UNKNOWN.asException() } for (service_uuid in dataTypesRequest.getIncompleteServiceClassUuids16List()) { advertisingDataBuilder.addServiceUuid(ParcelUuid.fromString(service_uuid)) for (service_uuid in dataTypesRequest.getCompleteServiceClassUuids16List()) { val uuid16 = "0000${service_uuid}-0000-1000-8000-00805F9B34FB" advertisingDataBuilder.addServiceUuid(ParcelUuid.fromString(uuid16)) } for (service_uuid in dataTypesRequest.getIncompleteServiceClassUuids32List()) { for (service_uuid in dataTypesRequest.getCompleteServiceClassUuids32List()) { val uuid32 = "${service_uuid}-0000-1000-8000-00805F9B34FB" advertisingDataBuilder.addServiceUuid(ParcelUuid.fromString(service_uuid)) } for (service_uuid in dataTypesRequest.getIncompleteServiceClassUuids128List()) { for (service_uuid in dataTypesRequest.getCompleteServiceClassUuids128List()) { advertisingDataBuilder.addServiceUuid(ParcelUuid.fromString(service_uuid)) } Loading Loading @@ -651,18 +653,24 @@ class Host( if (BluetoothUuid.is16BitUuid(parcelUuid)) { val uuid16 = parcelUuid.uuid.toString().substring(4, 8).uppercase() dataTypesBuilder.addIncompleteServiceClassUuids16(uuid16) dataTypesBuilder.putServiceDataUuid16(uuid16, ByteString.copyFrom(serviceDataEntry.value)) dataTypesBuilder.putServiceDataUuid16( uuid16, ByteString.copyFrom(serviceDataEntry.value) ) } else if (BluetoothUuid.is32BitUuid(parcelUuid)) { val uuid32 = parcelUuid.uuid.toString().substring(0, 8).uppercase() dataTypesBuilder.addIncompleteServiceClassUuids32(uuid32) dataTypesBuilder.putServiceDataUuid32(uuid32, ByteString.copyFrom(serviceDataEntry.value)) dataTypesBuilder.putServiceDataUuid32( uuid32, ByteString.copyFrom(serviceDataEntry.value) ) } else { val uuid128 = parcelUuid.uuid.toString().uppercase() dataTypesBuilder.addIncompleteServiceClassUuids128(uuid128) dataTypesBuilder.putServiceDataUuid128(uuid128, ByteString.copyFrom(serviceDataEntry.value)) dataTypesBuilder.putServiceDataUuid128( uuid128, ByteString.copyFrom(serviceDataEntry.value) ) } } // Flags DataTypes CSSv10 1.3 Flags Loading android/pandora/server/src/com/android/pandora/SecurityStorage.kt +11 −2 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.content.IntentFilter import android.util.Log import com.google.protobuf.BoolValue import com.google.protobuf.Empty import io.grpc.Status import io.grpc.stub.StreamObserver import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers Loading Loading @@ -75,8 +76,16 @@ class SecurityStorage(private val context: Context) : SecurityStorageImplBase() override fun deleteBond(request: DeleteBondRequest, responseObserver: StreamObserver<Empty>) { grpcUnary(globalScope, responseObserver) { check(request.getAddressCase() == DeleteBondRequest.AddressCase.PUBLIC) val bluetoothDevice = request.public.toBluetoothDevice(bluetoothAdapter) val (address, type) = when (request.getAddressCase()!!) { DeleteBondRequest.AddressCase.PUBLIC -> Pair(request.public, BluetoothDevice.ADDRESS_TYPE_PUBLIC) DeleteBondRequest.AddressCase.RANDOM -> Pair(request.random, BluetoothDevice.ADDRESS_TYPE_RANDOM) DeleteBondRequest.AddressCase.ADDRESS_NOT_SET -> throw Status.UNKNOWN.asException() } val bluetoothDevice = bluetoothAdapter.getRemoteLeDevice(address.decodeAsMacAddressToString(), type) Log.i(TAG, "deleteBond: device=$bluetoothDevice") val unbonded = Loading Loading
android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +73 −48 Original line number Diff line number Diff line Loading @@ -182,10 +182,8 @@ public class LeAudioService extends ProfileService { private BroadcastReceiver mMuteStateChangedReceiver; private int mStoredRingerMode = -1; private Handler mHandler = new Handler(Looper.getMainLooper()); private final AudioManagerAddAudioDeviceCallback mAudioManagerAddAudioDeviceCallback = new AudioManagerAddAudioDeviceCallback(); private final AudioManagerRemoveAudioDeviceCallback mAudioManagerRemoveAudioDeviceCallback = new AudioManagerRemoveAudioDeviceCallback(); private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback = new AudioManagerAudioDeviceCallback(); private final Map<Integer, Integer> mBroadcastStateMap = new HashMap<>(); private final Map<Integer, Boolean> mBroadcastsPlaybackMap = new HashMap<>(); Loading Loading @@ -281,6 +279,9 @@ public class LeAudioService extends ProfileService { mTmapGattServer = LeAudioObjectsFactory.getInstance().getTmapGattServer(this); mTmapGattServer.start(tmapRoleMask); mAudioManager.registerAudioDeviceCallback(mAudioManagerAudioDeviceCallback, mHandler); // Mark service as started setLeAudioService(this); Loading Loading @@ -399,8 +400,7 @@ public class LeAudioService extends ProfileService { } } mAudioManager.unregisterAudioDeviceCallback(mAudioManagerAddAudioDeviceCallback); mAudioManager.unregisterAudioDeviceCallback(mAudioManagerRemoveAudioDeviceCallback); mAudioManager.unregisterAudioDeviceCallback(mAudioManagerAudioDeviceCallback); mAdapterService = null; mAudioManager = null; Loading Loading @@ -995,54 +995,85 @@ public class LeAudioService extends ProfileService { * is added or removed. */ @VisibleForTesting void notifyActiveDeviceChanged() { void notifyActiveDeviceChanged(BluetoothDevice device) { if (DBG) { Log.d(TAG, "Notify Active device changed." + device + ". Currently active device is " + mActiveAudioOutDevice); } Intent intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mActiveAudioOutDevice != null ? mActiveAudioOutDevice : mActiveAudioInDevice); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); sendBroadcast(intent, BLUETOOTH_CONNECT); } /* Notifications of audio device disconnection events. */ private class AudioManagerRemoveAudioDeviceCallback extends AudioDeviceCallback { /* Notifications of audio device connection/disconn events. */ private class AudioManagerAudioDeviceCallback extends AudioDeviceCallback { @Override public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) { if (mAudioManager == null) { public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) { if (mAudioManager == null || mAdapterService == null) { Log.e(TAG, "Callback called when LeAudioService is stopped"); return; } for (AudioDeviceInfo deviceInfo : removedDevices) { if (deviceInfo.getType() == AudioDeviceInfo.TYPE_BLE_HEADSET || deviceInfo.getType() == AudioDeviceInfo.TYPE_BLE_SPEAKER) { notifyActiveDeviceChanged(); if (DBG) { Log.d(TAG, " onAudioDevicesRemoved: device type: " + deviceInfo.getType()); for (AudioDeviceInfo deviceInfo : addedDevices) { if ((deviceInfo.getType() != AudioDeviceInfo.TYPE_BLE_HEADSET) && (deviceInfo.getType() != AudioDeviceInfo.TYPE_BLE_SPEAKER)) { continue; } mAudioManager.unregisterAudioDeviceCallback(this); String address = deviceInfo.getAddress(); if (address.equals("00:00:00:00:00:00")) { continue; } byte[] addressBytes = Utils.getBytesFromAddress(address); BluetoothDevice device = mAdapterService.getDeviceFromByte(addressBytes); if (DBG) { Log.d(TAG, " onAudioDevicesAdded: " + device + ", device type: " + deviceInfo.getType() + ", isSink: " + deviceInfo.isSink() + " isSource: " + deviceInfo.isSource()); } if ((deviceInfo.isSink() && !device.equals(mActiveAudioOutDevice)) || (deviceInfo.isSource() && !device.equals(mActiveAudioInDevice))) { Log.e(TAG, "Added device does not match to the one activated here. (" + device + " != " + mActiveAudioOutDevice + " / " + mActiveAudioInDevice + ")"); continue; } notifyActiveDeviceChanged(device); return; } } /* Notifications of audio device connection events. */ private class AudioManagerAddAudioDeviceCallback extends AudioDeviceCallback { @Override public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) { if (mAudioManager == null) { public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) { if (mAudioManager == null || mAdapterService == null) { Log.e(TAG, "Callback called when LeAudioService is stopped"); return; } for (AudioDeviceInfo deviceInfo : addedDevices) { if (deviceInfo.getType() == AudioDeviceInfo.TYPE_BLE_HEADSET || deviceInfo.getType() == AudioDeviceInfo.TYPE_BLE_SPEAKER) { notifyActiveDeviceChanged(); if (DBG) { Log.d(TAG, " onAudioDevicesAdded: device type: " + deviceInfo.getType()); for (AudioDeviceInfo deviceInfo : removedDevices) { if ((deviceInfo.getType() != AudioDeviceInfo.TYPE_BLE_HEADSET) && (deviceInfo.getType() != AudioDeviceInfo.TYPE_BLE_SPEAKER)) { continue; } mAudioManager.unregisterAudioDeviceCallback(this); String address = deviceInfo.getAddress(); if (address.equals("00:00:00:00:00:00")) { continue; } if (DBG) { Log.d(TAG, " onAudioDevicesRemoved: " + address + ", device type: " + deviceInfo.getType() + ", isSink: " + deviceInfo.isSink() + " isSource: " + deviceInfo.isSource() + ", mActiveAudioInDevice: " + mActiveAudioInDevice + ", mActiveAudioOutDevice: " + mActiveAudioOutDevice); } } } Loading Loading @@ -1077,20 +1108,6 @@ public class LeAudioService extends ProfileService { + ", " + mActiveAudioInDevice); } /* Active device changed, there is need to inform about new active LE Audio device */ if (isNewActiveOutDevice || isNewActiveInDevice) { /* Register for new device connection/disconnection in Audio Manager */ if (mActiveAudioOutDevice != null || mActiveAudioInDevice != null) { /* Register for any device connection in case if any of devices become connected */ mAudioManager.registerAudioDeviceCallback(mAudioManagerAddAudioDeviceCallback, mHandler); } else { /* Register for disconnection if active devices become non-active */ mAudioManager.registerAudioDeviceCallback(mAudioManagerRemoveAudioDeviceCallback, mHandler); } } if (isNewActiveOutDevice) { int volume = IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME; Loading @@ -1112,6 +1129,14 @@ public class LeAudioService extends ProfileService { false)); } if ((mActiveAudioOutDevice == null) && (mActiveAudioInDevice == null)) { /* Notify about inactive device as soon as possible. * When adding new device, wait with notification until AudioManager is ready * with adding the device. */ notifyActiveDeviceChanged(null); } return mActiveAudioOutDevice != null; } Loading
android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java +3 −3 Original line number Diff line number Diff line Loading @@ -1147,7 +1147,7 @@ public class LeAudioServiceTest { /* Since LeAudioService called AudioManager - assume Audio manager calles properly callback * mAudioManager.onAudioDeviceAdded */ mService.notifyActiveDeviceChanged(); mService.notifyActiveDeviceChanged(mSingleDevice); String action = BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED; Intent intent = TestUtils.waitForIntent(TIMEOUT_MS, mDeviceQueueMap.get(mSingleDevice)); Loading Loading @@ -1363,7 +1363,7 @@ public class LeAudioServiceTest { /* Since LeAudioService called AudioManager - assume Audio manager calles properly callback * mAudioManager.onAudioDeviceAdded */ mService.notifyActiveDeviceChanged(); mService.notifyActiveDeviceChanged(leadDevice); doReturn(BluetoothDevice.BOND_BONDED).when(mAdapterService).getBondState(leadDevice); verifyActiveDeviceStateIntent(AUDIO_MANAGER_DEVICE_ADD_TIMEOUT_MS, leadDevice); injectNoVerifyDeviceDisconnected(leadDevice); Loading Loading @@ -1432,7 +1432,7 @@ public class LeAudioServiceTest { /* Since LeAudioService called AudioManager - assume Audio manager calles properly callback * mAudioManager.onAudioDeviceAdded */ mService.notifyActiveDeviceChanged(); mService.notifyActiveDeviceChanged(leadDevice); verifyActiveDeviceStateIntent(AUDIO_MANAGER_DEVICE_ADD_TIMEOUT_MS, leadDevice); /* We don't want to distribute DISCONNECTION event, instead will try to reconnect Loading
android/pandora/mmi2grpc/mmi2grpc/gap.py +1 −1 Original line number Diff line number Diff line Loading @@ -207,7 +207,7 @@ class GAPProxy(ProfileProxy): self.host.StartAdvertising( own_address_type=OwnAddressType.PUBLIC, data=DataTypes(incomplete_service_class_uuids128=["955798ce-3022-455c-b759-ee8edcd73d1a"],)) data=DataTypes(complete_service_class_uuids128=["955798ce-3022-455c-b759-ee8edcd73d1a"],)) return "OK" @assert_description Loading
android/pandora/server/src/com/android/pandora/Host.kt +23 −15 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ import android.bluetooth.BluetoothDevice.TRANSPORT_BREDR import android.bluetooth.BluetoothDevice.TRANSPORT_LE import android.bluetooth.BluetoothManager import android.bluetooth.BluetoothProfile import android.bluetooth.BluetoothUuid; import android.bluetooth.BluetoothUuid import android.bluetooth.le.AdvertiseCallback import android.bluetooth.le.AdvertiseData import android.bluetooth.le.AdvertiseSettings Loading Loading @@ -550,21 +550,23 @@ class Host( val dataTypesRequest = request.data if ( !dataTypesRequest.getCompleteServiceClassUuids16List().isEmpty() or !dataTypesRequest.getCompleteServiceClassUuids32List().isEmpty() or !dataTypesRequest.getCompleteServiceClassUuids128List().isEmpty() !dataTypesRequest.getIncompleteServiceClassUuids16List().isEmpty() or !dataTypesRequest.getIncompleteServiceClassUuids32List().isEmpty() or !dataTypesRequest.getIncompleteServiceClassUuids128List().isEmpty() ) { Log.e(TAG, "Complete Service Class Uuids not supported") Log.e(TAG, "Incomplete Service Class Uuids not supported") throw Status.UNKNOWN.asException() } for (service_uuid in dataTypesRequest.getIncompleteServiceClassUuids16List()) { advertisingDataBuilder.addServiceUuid(ParcelUuid.fromString(service_uuid)) for (service_uuid in dataTypesRequest.getCompleteServiceClassUuids16List()) { val uuid16 = "0000${service_uuid}-0000-1000-8000-00805F9B34FB" advertisingDataBuilder.addServiceUuid(ParcelUuid.fromString(uuid16)) } for (service_uuid in dataTypesRequest.getIncompleteServiceClassUuids32List()) { for (service_uuid in dataTypesRequest.getCompleteServiceClassUuids32List()) { val uuid32 = "${service_uuid}-0000-1000-8000-00805F9B34FB" advertisingDataBuilder.addServiceUuid(ParcelUuid.fromString(service_uuid)) } for (service_uuid in dataTypesRequest.getIncompleteServiceClassUuids128List()) { for (service_uuid in dataTypesRequest.getCompleteServiceClassUuids128List()) { advertisingDataBuilder.addServiceUuid(ParcelUuid.fromString(service_uuid)) } Loading Loading @@ -651,18 +653,24 @@ class Host( if (BluetoothUuid.is16BitUuid(parcelUuid)) { val uuid16 = parcelUuid.uuid.toString().substring(4, 8).uppercase() dataTypesBuilder.addIncompleteServiceClassUuids16(uuid16) dataTypesBuilder.putServiceDataUuid16(uuid16, ByteString.copyFrom(serviceDataEntry.value)) dataTypesBuilder.putServiceDataUuid16( uuid16, ByteString.copyFrom(serviceDataEntry.value) ) } else if (BluetoothUuid.is32BitUuid(parcelUuid)) { val uuid32 = parcelUuid.uuid.toString().substring(0, 8).uppercase() dataTypesBuilder.addIncompleteServiceClassUuids32(uuid32) dataTypesBuilder.putServiceDataUuid32(uuid32, ByteString.copyFrom(serviceDataEntry.value)) dataTypesBuilder.putServiceDataUuid32( uuid32, ByteString.copyFrom(serviceDataEntry.value) ) } else { val uuid128 = parcelUuid.uuid.toString().uppercase() dataTypesBuilder.addIncompleteServiceClassUuids128(uuid128) dataTypesBuilder.putServiceDataUuid128(uuid128, ByteString.copyFrom(serviceDataEntry.value)) dataTypesBuilder.putServiceDataUuid128( uuid128, ByteString.copyFrom(serviceDataEntry.value) ) } } // Flags DataTypes CSSv10 1.3 Flags Loading
android/pandora/server/src/com/android/pandora/SecurityStorage.kt +11 −2 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.content.IntentFilter import android.util.Log import com.google.protobuf.BoolValue import com.google.protobuf.Empty import io.grpc.Status import io.grpc.stub.StreamObserver import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers Loading Loading @@ -75,8 +76,16 @@ class SecurityStorage(private val context: Context) : SecurityStorageImplBase() override fun deleteBond(request: DeleteBondRequest, responseObserver: StreamObserver<Empty>) { grpcUnary(globalScope, responseObserver) { check(request.getAddressCase() == DeleteBondRequest.AddressCase.PUBLIC) val bluetoothDevice = request.public.toBluetoothDevice(bluetoothAdapter) val (address, type) = when (request.getAddressCase()!!) { DeleteBondRequest.AddressCase.PUBLIC -> Pair(request.public, BluetoothDevice.ADDRESS_TYPE_PUBLIC) DeleteBondRequest.AddressCase.RANDOM -> Pair(request.random, BluetoothDevice.ADDRESS_TYPE_RANDOM) DeleteBondRequest.AddressCase.ADDRESS_NOT_SET -> throw Status.UNKNOWN.asException() } val bluetoothDevice = bluetoothAdapter.getRemoteLeDevice(address.decodeAsMacAddressToString(), type) Log.i(TAG, "deleteBond: device=$bluetoothDevice") val unbonded = Loading