summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--OWNERS23
-rw-r--r--OWNERS_automotive3
-rw-r--r--OWNERS_build1
-rw-r--r--OWNERS_channel_sounding9
-rw-r--r--OWNERS_chromeos22
-rw-r--r--OWNERS_content2
-rw-r--r--OWNERS_cs2
-rw-r--r--OWNERS_hearingaid1
-rw-r--r--OWNERS_leaudio3
-rw-r--r--TEST_MAPPING6
-rw-r--r--android/BluetoothLegacyMigration/OWNERS5
-rw-r--r--android/ChannelSoundingTestApp/OWNERS1
-rw-r--r--android/apishim/OWNERS6
-rw-r--r--android/app/OWNERS15
-rw-r--r--android/app/aidl/android/bluetooth/BluetoothClass.aidl2
-rw-r--r--android/app/aidl/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl2
-rw-r--r--android/app/aidl/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl2
-rw-r--r--android/app/aidl/android/bluetooth/IBluetooth.aidl2
-rw-r--r--android/app/aidl/android/bluetooth/IBluetoothCallback.aidl2
-rw-r--r--android/app/aidl/android/bluetooth/IBluetoothSocketManager.aidl2
-rw-r--r--android/app/aidl/android/bluetooth/IncomingRfcommSocketInfo.aidl2
-rw-r--r--android/app/jni/OWNERS4
-rw-r--r--android/app/jni/com_android_bluetooth_gatt.cpp6
-rw-r--r--android/app/jni/com_android_bluetooth_hfp.cpp7
-rw-r--r--android/app/res/values-as/strings.xml8
-rw-r--r--android/app/src/com/android/bluetooth/BluetoothMethodProxy.java5
-rw-r--r--android/app/src/com/android/bluetooth/BluetoothObexTransport.java6
-rw-r--r--android/app/src/com/android/bluetooth/Utils.java12
-rw-r--r--android/app/src/com/android/bluetooth/a2dp/A2dpNativeInterface.java15
-rw-r--r--android/app/src/com/android/bluetooth/a2dp/A2dpService.java336
-rw-r--r--android/app/src/com/android/bluetooth/a2dp/A2dpServiceBinder.java336
-rw-r--r--android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkNativeInterface.java15
-rw-r--r--android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java139
-rw-r--r--android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceBinder.java157
-rw-r--r--android/app/src/com/android/bluetooth/a2dpsink/OWNERS1
-rw-r--r--android/app/src/com/android/bluetooth/audio_util/MediaBrowserWrapper.java2
-rw-r--r--android/app/src/com/android/bluetooth/avrcp/AvrcpNativeInterface.java16
-rw-r--r--android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java90
-rw-r--r--android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceBinder.java116
-rw-r--r--android/app/src/com/android/bluetooth/avrcpcontroller/OWNERS1
-rw-r--r--android/app/src/com/android/bluetooth/bass_client/BassClientService.java238
-rw-r--r--android/app/src/com/android/bluetooth/bass_client/BassClientServiceBinder.java268
-rw-r--r--android/app/src/com/android/bluetooth/bass_client/OWNERS1
-rw-r--r--android/app/src/com/android/bluetooth/btservice/AdapterProperties.java16
-rw-r--r--android/app/src/com/android/bluetooth/btservice/AdapterService.java2534
-rw-r--r--android/app/src/com/android/bluetooth/btservice/AdapterServiceBinder.java2262
-rw-r--r--android/app/src/com/android/bluetooth/btservice/BluetoothSocketManagerBinder.java15
-rw-r--r--android/app/src/com/android/bluetooth/btservice/MetricsLogger.java111
-rw-r--r--android/app/src/com/android/bluetooth/btservice/RemoteDevices.java106
-rw-r--r--android/app/src/com/android/bluetooth/btservice/SilenceDeviceManager.java2
-rw-r--r--android/app/src/com/android/bluetooth/content_profiles/OWNERS1
-rw-r--r--android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java170
-rw-r--r--android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorServiceBinder.java194
-rw-r--r--android/app/src/com/android/bluetooth/csip/OWNERS1
-rw-r--r--android/app/src/com/android/bluetooth/gatt/AppAdvertiseStats.java51
-rw-r--r--android/app/src/com/android/bluetooth/gatt/GattService.java618
-rw-r--r--android/app/src/com/android/bluetooth/gatt/GattServiceBinder.java499
-rw-r--r--android/app/src/com/android/bluetooth/hap/HapClientService.java2
-rw-r--r--android/app/src/com/android/bluetooth/hap/HapClientServiceBinder.java (renamed from android/app/src/com/android/bluetooth/hap/HapClientBinder.java)31
-rw-r--r--android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java216
-rw-r--r--android/app/src/com/android/bluetooth/hearingaid/HearingAidServiceBinder.java230
-rw-r--r--android/app/src/com/android/bluetooth/hearingaid/OWNERS1
-rw-r--r--android/app/src/com/android/bluetooth/hfp/HeadsetNativeInterface.java16
-rw-r--r--android/app/src/com/android/bluetooth/hfp/HeadsetService.java317
-rw-r--r--android/app/src/com/android/bluetooth/hfp/HeadsetServiceBinder.java319
-rw-r--r--android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java6
-rw-r--r--android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java344
-rw-r--r--android/app/src/com/android/bluetooth/hfpclient/HeadsetClientServiceBinder.java345
-rw-r--r--android/app/src/com/android/bluetooth/hfpclient/NativeInterface.java9
-rw-r--r--android/app/src/com/android/bluetooth/hfpclient/OWNERS1
-rw-r--r--android/app/src/com/android/bluetooth/hid/HidDeviceNativeInterface.java11
-rw-r--r--android/app/src/com/android/bluetooth/hid/HidDeviceService.java202
-rw-r--r--android/app/src/com/android/bluetooth/hid/HidDeviceServiceBinder.java218
-rw-r--r--android/app/src/com/android/bluetooth/hid/HidHostService.java236
-rw-r--r--android/app/src/com/android/bluetooth/hid/HidHostServiceBinder.java232
-rw-r--r--android/app/src/com/android/bluetooth/le_audio/LeAudioService.java650
-rw-r--r--android/app/src/com/android/bluetooth/le_audio/LeAudioServiceBinder.java548
-rw-r--r--android/app/src/com/android/bluetooth/le_audio/OWNERS1
-rw-r--r--android/app/src/com/android/bluetooth/le_scan/AppScanStats.java203
-rw-r--r--android/app/src/com/android/bluetooth/le_scan/ScanController.java39
-rw-r--r--android/app/src/com/android/bluetooth/le_scan/ScanManager.java12
-rw-r--r--android/app/src/com/android/bluetooth/map/BluetoothMapService.java228
-rw-r--r--android/app/src/com/android/bluetooth/map/BluetoothMapServiceBinder.java251
-rw-r--r--android/app/src/com/android/bluetooth/map/OWNERS1
-rw-r--r--android/app/src/com/android/bluetooth/mapclient/MapClientService.java177
-rw-r--r--android/app/src/com/android/bluetooth/mapclient/MapClientServiceBinder.java193
-rw-r--r--android/app/src/com/android/bluetooth/mapclient/OWNERS2
-rw-r--r--android/app/src/com/android/bluetooth/mcp/McpService.java42
-rw-r--r--android/app/src/com/android/bluetooth/mcp/McpServiceBinder.java63
-rw-r--r--android/app/src/com/android/bluetooth/mcp/OWNERS1
-rw-r--r--android/app/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java6
-rw-r--r--android/app/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java15
-rw-r--r--android/app/src/com/android/bluetooth/opp/BluetoothOppManager.java13
-rw-r--r--android/app/src/com/android/bluetooth/opp/BluetoothOppPreference.java23
-rw-r--r--android/app/src/com/android/bluetooth/opp/BluetoothOppReceiver.java5
-rw-r--r--android/app/src/com/android/bluetooth/opp/BluetoothOppService.java6
-rw-r--r--android/app/src/com/android/bluetooth/opp/BluetoothOppTransfer.java18
-rw-r--r--android/app/src/com/android/bluetooth/opp/BluetoothOppUtility.java31
-rw-r--r--android/app/src/com/android/bluetooth/opp/OWNERS1
-rw-r--r--android/app/src/com/android/bluetooth/pan/OWNERS1
-rw-r--r--android/app/src/com/android/bluetooth/pan/PanService.java157
-rw-r--r--android/app/src/com/android/bluetooth/pan/PanServiceBinder.java161
-rw-r--r--android/app/src/com/android/bluetooth/pbap/BluetoothPbapActivity.java2
-rw-r--r--android/app/src/com/android/bluetooth/pbap/BluetoothPbapAuthenticator.java2
-rw-r--r--android/app/src/com/android/bluetooth/pbap/BluetoothPbapConfig.java2
-rw-r--r--android/app/src/com/android/bluetooth/pbap/BluetoothPbapObexServer.java2
-rw-r--r--android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java101
-rw-r--r--android/app/src/com/android/bluetooth/pbap/BluetoothPbapServiceBinder.java121
-rw-r--r--android/app/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManager.java2
-rw-r--r--android/app/src/com/android/bluetooth/pbap/BluetoothPbapUtils.java2
-rw-r--r--android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java2
-rw-r--r--android/app/src/com/android/bluetooth/pbap/OWNERS1
-rw-r--r--android/app/src/com/android/bluetooth/pbapclient/OWNERS2
-rw-r--r--android/app/src/com/android/bluetooth/pbapclient/PbapClientService.java2
-rw-r--r--android/app/src/com/android/bluetooth/pbapclient/PbapClientServiceBinder.java (renamed from android/app/src/com/android/bluetooth/pbapclient/PbapClientBinder.java)6
-rw-r--r--android/app/src/com/android/bluetooth/sap/OWNERS1
-rw-r--r--android/app/src/com/android/bluetooth/sap/SapService.java147
-rw-r--r--android/app/src/com/android/bluetooth/sap/SapServiceBinder.java166
-rw-r--r--android/app/src/com/android/bluetooth/sdp/SdpManager.java25
-rw-r--r--android/app/src/com/android/bluetooth/tbs/TbsService.java114
-rw-r--r--android/app/src/com/android/bluetooth/tbs/TbsServiceBinder.java126
-rw-r--r--android/app/src/com/android/bluetooth/vc/OWNERS1
-rw-r--r--android/app/src/com/android/bluetooth/vc/VolumeControlService.java522
-rw-r--r--android/app/src/com/android/bluetooth/vc/VolumeControlServiceBinder.java528
-rw-r--r--android/app/tests/OWNERS1
-rw-r--r--android/app/tests/instrumentation/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java25
-rw-r--r--android/app/tests/unit/Android.bp11
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/OWNERS2
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceBinderTest.java16
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceBinderTest.java12
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceBinderTest.java20
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceBinderTest.java (renamed from android/app/tests/unit/src/com/android/bluetooth/bass_client/BleBroadcastAssistantBinderTest.java)14
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/bass_client/OWNERS1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceBinderTest.java18
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java8
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java60
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/content_profiles/OWNERS1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorServiceBinderTest.java (renamed from android/app/tests/unit/src/com/android/bluetooth/csip/BluetoothCsisBinderTest.java)19
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorServiceTest.java1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/csip/OWNERS1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseBinderTest.java202
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseBinderTest.kt201
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/gatt/AppAdvertiseStatsTest.java7
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementBinderTest.java119
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementBinderTest.kt112
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceBinderTest.java42
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java4
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/hap/HapClientServiceBinderTest.java (renamed from android/app/tests/unit/src/com/android/bluetooth/hap/HapClientBinderTest.java)7
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceBinderTest.java200
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceTest.java4
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/hearingaid/OWNERS1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java11
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceBinderTest.java (renamed from android/app/tests/unit/src/com/android/bluetooth/hfp/BluetoothHeadsetBinderTest.java)17
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceBinderTest.java59
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceServiceBinderTest.java (renamed from android/app/tests/unit/src/com/android/bluetooth/hid/BluetoothHidDeviceBinderTest.java)14
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceServiceTest.java (renamed from android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java)2
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java51
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java2
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceBinderTest.java (renamed from android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBinderTest.java)14
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java100
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/le_audio/OWNERS1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanBinderTest.java194
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanBinderTest.kt187
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanManagerTest.java35
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceBinderTest.java34
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/map/OWNERS1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/mapapi/OWNERS1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceBinderTest.java31
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/mapclient/OWNERS1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/mcp/McpServiceBinderTest.java69
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/mcp/OWNERS1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/obex/OWNERS1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferTest.java1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java19
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/opp/OWNERS1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/pan/OWNERS1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceBinderTest.java29
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceBinderTest.java18
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/pbap/OWNERS1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/pbapclient/OWNERS1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientObexTransportTest.java1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceBinderTest.java (renamed from android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientBinderTest.java)58
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/sap/OWNERS1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/sap/SapServiceBinderTest.java132
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/tbs/TbsServiceBinderTest.java146
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/vc/OWNERS1
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceBinderTest.java294
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java4
-rw-r--r--android/leaudio/OWNERS1
-rw-r--r--android/pandora/OWNERS2
-rw-r--r--android/pandora/test/main.py2
-rw-r--r--android/pandora/test/pairing/OWNERS2
-rw-r--r--android/pandora/test/rfcomm_test.py110
-rw-r--r--apex/Android.bp1
-rw-r--r--apex/OWNERS4
-rw-r--r--apex/hiddenapi/OWNERS5
-rw-r--r--apex/permissions/OWNERS1
-rwxr-xr-xbuild.py1
-rw-r--r--common/OWNERS1
-rw-r--r--flags/OWNERS3
-rw-r--r--flags/a2dp.aconfig10
-rw-r--r--flags/bta_dm.aconfig10
-rw-r--r--flags/connectivity.aconfig24
-rw-r--r--flags/framework.aconfig10
-rw-r--r--flags/gap.aconfig81
-rw-r--r--flags/hci.aconfig7
-rw-r--r--flags/hfp.aconfig10
-rw-r--r--flags/hid.aconfig40
-rw-r--r--flags/l2cap.aconfig10
-rw-r--r--flags/leaudio.aconfig10
-rw-r--r--flags/opp.aconfig27
-rw-r--r--flags/pairing.aconfig40
-rw-r--r--flags/security.aconfig17
-rw-r--r--flags/sockets.aconfig10
-rw-r--r--flags/system_service.aconfig10
-rw-r--r--floss/OWNERS1
-rw-r--r--floss/pandora/OWNERS4
-rw-r--r--framework/OWNERS4
-rw-r--r--framework/api/system-current.txt1
-rw-r--r--framework/java/android/bluetooth/BluetoothAdapter.java3
-rw-r--r--framework/java/android/bluetooth/BluetoothDevicePicker.java11
-rw-r--r--framework/java/android/bluetooth/OWNERS5
-rw-r--r--framework/java/android/bluetooth/le/DistanceMeasurementManager.java11
-rw-r--r--framework/tests/bumble/src/android/bluetooth/DckScanTest.kt2
-rw-r--r--framework/tests/bumble/src/android/bluetooth/GattClientTest.java8
-rw-r--r--framework/tests/bumble/src/android/bluetooth/hid/HidHeadTrackerTest.java9
-rw-r--r--framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java6
-rw-r--r--framework/tests/bumble/src/android/bluetooth/hid/OWNERS3
-rw-r--r--framework/tests/bumble/src/android/bluetooth/pairing/OWNERS3
-rw-r--r--framework/tests/bumble/src/android/bluetooth/pairing/OobPairingTest.java9
-rw-r--r--framework/tests/bumble/src/android/bluetooth/service_discovery/OWNERS3
-rw-r--r--framework/tests/bumble/src/android/bluetooth/sockets/OWNERS3
-rw-r--r--framework/tests/metrics/OWNERS3
-rw-r--r--offload/leaudio/hci/proxy.rs30
-rw-r--r--pandora/OWNERS2
-rw-r--r--service/OWNERS1
-rw-r--r--service/src/com/android/server/bluetooth/BluetoothManagerService.java287
-rw-r--r--service/tests/Android.bp1
-rw-r--r--service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java304
-rw-r--r--sysprop/OWNERS1
-rw-r--r--system/BUILD.gn2
-rw-r--r--system/OWNERS18
-rw-r--r--system/audio_hal_interface/aidl/le_audio_software_aidl.cc26
-rw-r--r--system/bta/Android.bp72
-rw-r--r--system/bta/BUILD.gn1
-rw-r--r--system/bta/dm/bta_dm_act.cc2
-rw-r--r--system/bta/dm/bta_dm_disc.cc9
-rw-r--r--system/bta/dm/bta_dm_int.h4
-rw-r--r--system/bta/gatt/bta_gattc_act.cc272
-rw-r--r--system/bta/gatt/bta_gattc_utils.cc266
-rw-r--r--system/bta/hearing_aid/OWNERS1
-rw-r--r--system/bta/hearing_aid/hearing_aid_test.cc474
-rw-r--r--system/bta/hh/bta_hh_le.cc72
-rw-r--r--system/bta/include/OWNERS1
-rw-r--r--system/bta/le_audio/OWNERS1
-rw-r--r--system/bta/le_audio/broadcaster/broadcaster_test.cc9
-rw-r--r--system/bta/le_audio/codec_manager.cc10
-rw-r--r--system/bta/le_audio/codec_manager_test.cc26
-rw-r--r--system/bta/le_audio/devices_test.cc7
-rw-r--r--system/bta/le_audio/le_audio_client_test.cc13
-rw-r--r--system/bta/le_audio/metrics_collector.cc6
-rw-r--r--system/bta/le_audio/metrics_collector_test.cc10
-rw-r--r--system/bta/le_audio/state_machine.cc14
-rw-r--r--system/bta/le_audio/state_machine_test.cc7
-rw-r--r--system/bta/test/bta_ag_sco_test.cc6
-rw-r--r--system/bta/test/bta_ag_test.cc6
-rw-r--r--system/bta/test/bta_dm_test.cc11
-rw-r--r--system/bta/test/bta_sdp_test.cc11
-rw-r--r--system/bta/test/bta_test_fixtures.h6
-rw-r--r--system/bta/test/common/btif_storage_mock.cc15
-rw-r--r--system/bta/test/common/btif_storage_mock.h12
-rw-r--r--system/btcore/Android.bp40
-rw-r--r--system/btcore/BUILD.gn34
-rw-r--r--system/btcore/fuzzer/Android.bp97
-rw-r--r--system/btcore/fuzzer/README.md56
-rw-r--r--system/btcore/fuzzer/btcore_device_class_fuzzer.cpp70
-rw-r--r--system/btcore/fuzzer/btcore_module_fuzzer.cpp48
-rw-r--r--system/btcore/fuzzer/btcore_property_fuzzer.cpp96
-rw-r--r--system/btcore/include/device_class.h95
-rw-r--r--system/btcore/include/device_features.h27
-rw-r--r--system/btcore/include/event_mask.h28
-rw-r--r--system/btcore/include/iac.h28
-rw-r--r--system/btcore/include/property.h76
-rw-r--r--system/btcore/include/version.h29
-rw-r--r--system/btcore/src/device_class.cc167
-rw-r--r--system/btcore/src/property.cc217
-rw-r--r--system/btcore/test/device_class_test.cc224
-rw-r--r--system/btcore/test/property_test.cc269
-rw-r--r--system/btif/Android.bp1
-rw-r--r--system/btif/BUILD.gn1
-rw-r--r--system/btif/include/btif_metrics_logging.h72
-rw-r--r--system/btif/src/OWNERS1
-rw-r--r--system/btif/src/bluetooth.cc4
-rw-r--r--system/btif/src/btif_a2dp_source.cc41
-rw-r--r--system/btif/src/btif_av.cc31
-rw-r--r--system/btif/src/btif_config.cc15
-rw-r--r--system/btif/src/btif_dm.cc19
-rw-r--r--system/btif/src/btif_hf.cc23
-rw-r--r--system/btif/src/btif_hh.cc30
-rw-r--r--system/btif/src/btif_metrics_logging.cc111
-rw-r--r--system/btif/src/btif_sock_logging.cc4
-rw-r--r--system/btif/src/btif_sock_rfc.cc14
-rw-r--r--system/btif/test/btif_core_test.cc27
-rw-r--r--system/common/Android.bp11
-rw-r--r--system/common/BUILD.gn3
-rw-r--r--system/common/metrics.cc433
-rw-r--r--system/common/metrics.h272
-rw-r--r--system/common/metrics_linux.cc111
-rw-r--r--system/conf/interop_database.conf5
-rw-r--r--system/device/include/interop.h10
-rw-r--r--system/device/src/interop.cc1
-rw-r--r--system/gd/Android.bp10
-rw-r--r--system/gd/common/audit_log.cc6
-rw-r--r--system/gd/hal/hci_hal.h7
-rw-r--r--system/gd/hal/hci_hal_android_test.cc8
-rw-r--r--system/gd/hal/hci_hal_host.cc36
-rw-r--r--system/gd/hal/hci_hal_host_test.cc8
-rw-r--r--system/gd/hal/snoop_logger.h8
-rw-r--r--system/gd/hci/acl_manager.cc15
-rw-r--r--system/gd/hci/acl_manager.h7
-rw-r--r--system/gd/hci/acl_manager/le_impl.h56
-rw-r--r--system/gd/hci/acl_manager/le_impl_test.cc326
-rw-r--r--system/gd/hci/acl_manager/round_robin_scheduler.cc10
-rw-r--r--system/gd/hci/acl_manager/round_robin_scheduler_test.cc3
-rw-r--r--system/gd/hci/controller.cc4
-rw-r--r--system/gd/hci/distance_measurement_manager.cc108
-rw-r--r--system/gd/hci/distance_measurement_manager_test.cc380
-rw-r--r--system/gd/hci/hci_layer.cc41
-rw-r--r--system/gd/hci/hci_layer.h2
-rw-r--r--system/gd/hci/le_address_manager.cc58
-rw-r--r--system/gd/hci/le_advertising_manager.cc171
-rw-r--r--system/gd/metrics/chromeos/OWNERS1
-rw-r--r--system/gd/metrics/counter_metrics.h9
-rw-r--r--system/gd/metrics/linux/OWNERS1
-rw-r--r--system/gd/module.cc31
-rw-r--r--system/gd/module.h6
-rw-r--r--system/gd/module_unittest.cc6
-rw-r--r--system/gd/os/android/metrics.cc56
-rw-r--r--system/gd/os/chromeos/metrics.cc14
-rw-r--r--system/gd/os/host/metrics.cc14
-rw-r--r--system/gd/os/linux/metrics.cc15
-rw-r--r--system/gd/os/linux_generic/alarm.cc6
-rw-r--r--system/gd/os/metrics.h17
-rw-r--r--system/gd/rust/linux/OWNERS1
-rw-r--r--system/gd/rust/linux/service/src/interface_manager.rs48
-rw-r--r--system/gd/rust/linux/service/src/main.rs136
-rw-r--r--system/gd/rust/linux/stack/src/bluetooth.rs27
-rw-r--r--system/gd/rust/linux/stack/src/lib.rs8
-rw-r--r--system/gd/rust/topshim/OWNERS1
-rw-r--r--system/gd/storage/storage_module.cc7
-rw-r--r--system/include/hardware/bluetooth_headset_interface.h3
-rw-r--r--system/linux_include/log/log.h24
-rw-r--r--system/log/OWNERS1
-rw-r--r--system/main/shim/acl.cc11
-rw-r--r--system/main/shim/acl.h2
-rw-r--r--system/main/shim/acl_api.cc6
-rw-r--r--system/main/shim/acl_api.h2
-rw-r--r--system/main/shim/stack.cc50
-rw-r--r--system/main/test/main_shim_test.cc13
-rw-r--r--system/osi/BUILD.gn1
-rw-r--r--system/pdl/hci/hci_packets.pdl4
-rw-r--r--system/stack/Android.bp35
-rw-r--r--system/stack/BUILD.gn3
-rw-r--r--system/stack/acl/btm_acl.cc8
-rw-r--r--system/stack/btm/btm_ble_sec.cc24
-rw-r--r--system/stack/btm/btm_dev.cc6
-rw-r--r--system/stack/btm/btm_sco.cc5
-rw-r--r--system/stack/btm/btm_sec.cc35
-rw-r--r--system/stack/btm/security_event_parser.cc23
-rw-r--r--system/stack/btu/btu_hcif.cc135
-rw-r--r--system/stack/eatt/eatt_impl.h6
-rw-r--r--system/stack/fuzzers/l2cap_fuzzer.cc20
-rw-r--r--system/stack/gatt/gatt_api.cc91
-rw-r--r--system/stack/gatt/gatt_auth.cc15
-rw-r--r--system/stack/gatt/gatt_cl.cc49
-rw-r--r--system/stack/gatt/gatt_main.cc119
-rw-r--r--system/stack/gatt/gatt_sr.cc46
-rw-r--r--system/stack/gatt/gatt_utils.cc192
-rw-r--r--system/stack/hid/hidd_api.cc48
-rw-r--r--system/stack/hid/hidd_conn.cc33
-rw-r--r--system/stack/hid/hidh_api.cc30
-rw-r--r--system/stack/hid/hidh_conn.cc22
-rw-r--r--system/stack/include/l2cap_interface.h15
-rw-r--r--system/stack/include/stack_metrics_logging.h69
-rw-r--r--system/stack/l2cap/internal/l2c_api.h14
-rw-r--r--system/stack/l2cap/l2c_api.h2
-rw-r--r--system/stack/l2cap/l2c_ble.cc9
-rw-r--r--system/stack/l2cap/l2c_ble_conn_params.cc20
-rw-r--r--system/stack/l2cap/l2cap_api.cc7
-rw-r--r--system/stack/metrics/stack_metrics_logging.cc101
-rw-r--r--system/stack/mmc/OWNERS1
-rw-r--r--system/stack/mmc/metrics/mmc_rtt_logger.cc5
-rw-r--r--system/stack/rfcomm/port_api.cc4
-rw-r--r--system/stack/rfcomm/port_rfc.cc41
-rw-r--r--system/stack/rfcomm/rfc_l2cap_if.cc54
-rw-r--r--system/stack/sdp/sdp_utils.cc38
-rw-r--r--system/stack/smp/smp_l2c.cc7
-rw-r--r--system/stack/smp/smp_utils.cc10
-rw-r--r--system/stack/test/btm/stack_btm_power_mode_test.cc9
-rw-r--r--system/stack/test/btm/stack_btm_sec_test.cc5
-rw-r--r--system/stack/test/btm/stack_btm_test.cc39
-rw-r--r--system/stack/test/btm_iso_test.cc21
-rw-r--r--system/stack/test/connection_manager_test.cc59
-rw-r--r--system/stack/test/eatt/eatt_test.cc10
-rw-r--r--system/stack/test/gatt/gatt_sr_test.cc22
-rw-r--r--system/stack/test/sdp/stack_sdp_test.cc2
-rw-r--r--system/stack/test/stack_acl_test.cc6
-rw-r--r--system/stack/test/stack_l2cap_test.cc14
-rw-r--r--system/test/Android.bp16
-rw-r--r--system/test/README.md81
-rw-r--r--system/test/mock/mock_bta_hearing_aid_audio_source.cc43
-rw-r--r--system/test/mock/mock_main_shim_acl.cc6
-rw-r--r--system/test/mock/mock_main_shim_acl_api.cc6
-rw-r--r--system/test/mock/mock_main_shim_acl_api.h15
-rw-r--r--system/test/mock/mock_main_shim_entry.cc12
-rw-r--r--system/test/mock/mock_main_shim_entry.h9
-rw-r--r--system/test/mock/mock_stack_gap_conn_interface.cc (renamed from system/test/mock/mock_stack_gap_conn.cc)53
-rw-r--r--system/test/mock/mock_stack_gap_conn_interface.h63
-rw-r--r--system/test/mock/mock_stack_l2cap_interface.h3
-rw-r--r--system/test/mock/mock_stack_metrics_logging.cc151
-rw-r--r--system/test/mock/mock_stack_metrics_logging.h254
-rw-r--r--system/test/suite/adapter/adapter_unittest.cc51
-rw-r--r--system/test/suite/adapter/bluetooth_test.cc28
-rw-r--r--tools/OWNERS5
-rw-r--r--tools/lint/OWNERS2
-rw-r--r--tools/rootcanal/OWNERS3
426 files changed, 13596 insertions, 14490 deletions
diff --git a/OWNERS b/OWNERS
index 82367c3a5f..c73a7053d5 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,19 +1,6 @@
-# Bug component: 27441
+set noparent
-# Project owners
-girardier@google.com #{LAST_RESORT_SUGGESTION}
-muhammadfalam@google.com #{LAST_RESORT_SUGGESTION}
-siyuanh@google.com #{LAST_RESORT_SUGGESTION}
-okamil@google.com #{LAST_RESORT_SUGGESTION}
-wescande@google.com #{LAST_RESORT_SUGGESTION}
-
-# Per-file ownership
-
-# Build files / test_config / presubmit / preupload / linter file
-per-file *.cfg,.cfg,TEST_MAPPING,*.bp,*.xml,.clang-tidy,pyrightconfig.json=file:/OWNERS_build
-
-# ChromeOS team owns Linux build files
-# - build.py is used for Linux build
-# - *.gn is for GN build rules
-# - Cargo.toml is for Rust build rules
-per-file build.py,*.gn,Cargo.toml=file:/OWNERS_chromeos
+girardier@google.com
+muhammadfalam@google.com
+okamil@google.com
+siyuanh@google.com
diff --git a/OWNERS_automotive b/OWNERS_automotive
deleted file mode 100644
index 20c7ac685b..0000000000
--- a/OWNERS_automotive
+++ /dev/null
@@ -1,3 +0,0 @@
-# Project owners
-cmanton@google.com
-salsavage@google.com
diff --git a/OWNERS_build b/OWNERS_build
deleted file mode 100644
index 5b3f4bad26..0000000000
--- a/OWNERS_build
+++ /dev/null
@@ -1 +0,0 @@
-wescande@google.com
diff --git a/OWNERS_channel_sounding b/OWNERS_channel_sounding
deleted file mode 100644
index 10a8fa893a..0000000000
--- a/OWNERS_channel_sounding
+++ /dev/null
@@ -1,9 +0,0 @@
-# Pixel DRI
-aliceypkuo@google.com
-chienyuanhuang@google.com
-
-# Bluetooth Ranging DRI
-steveliu@google.com
-
-# Bluetooth Stack Reviewer
-henrichataing@google.com
diff --git a/OWNERS_chromeos b/OWNERS_chromeos
deleted file mode 100644
index 075a04e5e3..0000000000
--- a/OWNERS_chromeos
+++ /dev/null
@@ -1,22 +0,0 @@
-# Project owners
-abhishekpandit@google.com
-
-# Audio
-enshuo@google.com
-hychao@google.com
-jrwu@google.com
-whalechang@google.com
-
-# General review
-michaelfsun@google.com
-laikatherine@google.com
-yinghsu@google.com
-apusaka@google.com
-deanliao@google.com
-chharry@google.com
-melhuishj@google.com
-johnlai@google.com
-mmandlik@google.com
-sarveshkalwit@google.com
-howardchung@google.com
-jiangzp@google.com
diff --git a/OWNERS_content b/OWNERS_content
deleted file mode 100644
index 883d5dc782..0000000000
--- a/OWNERS_content
+++ /dev/null
@@ -1,2 +0,0 @@
-klhyun@google.com
-hdmoon@google.com
diff --git a/OWNERS_cs b/OWNERS_cs
deleted file mode 100644
index 1cebb11002..0000000000
--- a/OWNERS_cs
+++ /dev/null
@@ -1,2 +0,0 @@
-steveliu@google.com
-zning@google.com
diff --git a/OWNERS_hearingaid b/OWNERS_hearingaid
deleted file mode 100644
index d1c75de900..0000000000
--- a/OWNERS_hearingaid
+++ /dev/null
@@ -1 +0,0 @@
-henrichataing@google.com
diff --git a/OWNERS_leaudio b/OWNERS_leaudio
deleted file mode 100644
index 30db38d799..0000000000
--- a/OWNERS_leaudio
+++ /dev/null
@@ -1,3 +0,0 @@
-siyuanh@google.com
-jpawlowski@google.com
-rongxuan@google.com
diff --git a/TEST_MAPPING b/TEST_MAPPING
index b1cc9a7594..c807f7d8ec 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -133,9 +133,6 @@
"name": "net_test_bta_security"
},
{
- "name": "net_test_btcore"
- },
- {
"name": "net_test_btif"
},
{
@@ -365,9 +362,6 @@
"name": "net_test_bta_security"
},
{
- "name": "net_test_btcore"
- },
- {
"name": "net_test_btif"
},
{
diff --git a/android/BluetoothLegacyMigration/OWNERS b/android/BluetoothLegacyMigration/OWNERS
deleted file mode 100644
index 66467c7b3e..0000000000
--- a/android/BluetoothLegacyMigration/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Reviewers for /android/BluetoothLegacyMigration
-
-eruffieux@google.com
-siyuanh@google.com
-wescande@google.com
diff --git a/android/ChannelSoundingTestApp/OWNERS b/android/ChannelSoundingTestApp/OWNERS
deleted file mode 100644
index 29d6f601cc..0000000000
--- a/android/ChannelSoundingTestApp/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_cs
diff --git a/android/apishim/OWNERS b/android/apishim/OWNERS
deleted file mode 100644
index 586d2866f1..0000000000
--- a/android/apishim/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-# Reviewers for /android/apishim
-
-eruffieux@google.com
-jpawlowski@google.com
-siyuanh@google.com
-wescande@google.com
diff --git a/android/app/OWNERS b/android/app/OWNERS
deleted file mode 100644
index 7b7e2e6679..0000000000
--- a/android/app/OWNERS
+++ /dev/null
@@ -1,15 +0,0 @@
-# Reviewers for /android/app
-
-bhaktha@google.com
-eruffieux@google.com
-hallstrom@google.com
-henrichataing@google.com
-jpawlowski@google.com
-okamil@google.com
-poahlo@google.com
-siyuanh@google.com
-wescande@google.com
-rwt@google.com
-
-# Reviewers for Channel Sounding related files
-per-file /src/com/android/bluetooth/gatt/DistanceMeasurement*.java=file:/OWNERS_channel_sounding
diff --git a/android/app/aidl/android/bluetooth/BluetoothClass.aidl b/android/app/aidl/android/bluetooth/BluetoothClass.aidl
index 8699b1eee3..124ee53760 100644
--- a/android/app/aidl/android/bluetooth/BluetoothClass.aidl
+++ b/android/app/aidl/android/bluetooth/BluetoothClass.aidl
@@ -5,7 +5,7 @@
* 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
+ * 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,
diff --git a/android/app/aidl/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl b/android/app/aidl/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl
index 14f91140af..74f51a8037 100644
--- a/android/app/aidl/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl
+++ b/android/app/aidl/android/bluetooth/BluetoothHidDeviceAppQosSettings.aidl
@@ -5,7 +5,7 @@
** 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
+** 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,
diff --git a/android/app/aidl/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl b/android/app/aidl/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl
index 87dd10ee15..a55a794c6e 100644
--- a/android/app/aidl/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl
+++ b/android/app/aidl/android/bluetooth/BluetoothHidDeviceAppSdpSettings.aidl
@@ -5,7 +5,7 @@
** 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
+** 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,
diff --git a/android/app/aidl/android/bluetooth/IBluetooth.aidl b/android/app/aidl/android/bluetooth/IBluetooth.aidl
index bc46353f7c..d8a5421d6f 100644
--- a/android/app/aidl/android/bluetooth/IBluetooth.aidl
+++ b/android/app/aidl/android/bluetooth/IBluetooth.aidl
@@ -5,7 +5,7 @@
* 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
+ * 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,
diff --git a/android/app/aidl/android/bluetooth/IBluetoothCallback.aidl b/android/app/aidl/android/bluetooth/IBluetoothCallback.aidl
index 9b2888eadb..6101044e29 100644
--- a/android/app/aidl/android/bluetooth/IBluetoothCallback.aidl
+++ b/android/app/aidl/android/bluetooth/IBluetoothCallback.aidl
@@ -5,7 +5,7 @@
* 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
+ * 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,
diff --git a/android/app/aidl/android/bluetooth/IBluetoothSocketManager.aidl b/android/app/aidl/android/bluetooth/IBluetoothSocketManager.aidl
index ce2397ff33..bd54982d13 100644
--- a/android/app/aidl/android/bluetooth/IBluetoothSocketManager.aidl
+++ b/android/app/aidl/android/bluetooth/IBluetoothSocketManager.aidl
@@ -5,7 +5,7 @@
* 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
+ * 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,
diff --git a/android/app/aidl/android/bluetooth/IncomingRfcommSocketInfo.aidl b/android/app/aidl/android/bluetooth/IncomingRfcommSocketInfo.aidl
index 38ffe6f699..c3d542c774 100644
--- a/android/app/aidl/android/bluetooth/IncomingRfcommSocketInfo.aidl
+++ b/android/app/aidl/android/bluetooth/IncomingRfcommSocketInfo.aidl
@@ -5,7 +5,7 @@
* 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
+ * 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,
diff --git a/android/app/jni/OWNERS b/android/app/jni/OWNERS
deleted file mode 100644
index 826f56b4e0..0000000000
--- a/android/app/jni/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-per-file com_android_bluetooth_hearing_aid.cpp=file:/OWNERS_hearingaid
-per-file com_android_bluetooth_csip_set_coordinator.cpp=file:/OWNERS_leaudio
-per-file com_android_bluetooth_le_audio.cpp=file:/OWNERS_leaudio
-per-file com_android_bluetooth_vc.cpp=file:/OWNERS_leaudio
diff --git a/android/app/jni/com_android_bluetooth_gatt.cpp b/android/app/jni/com_android_bluetooth_gatt.cpp
index acd609f8bd..be0922c8fc 100644
--- a/android/app/jni/com_android_bluetooth_gatt.cpp
+++ b/android/app/jni/com_android_bluetooth_gatt.cpp
@@ -2353,7 +2353,11 @@ static AdvertiseParameters parseParams(JNIEnv* env, jobject i) {
p.secondary_advertising_phy = secondaryPhy;
p.scan_request_notification_enable = false;
p.own_address_type = ownAddressType;
- p.peer_address = str2addr(env, peerAddress);
+ if (peerAddress == nullptr) {
+ p.peer_address = RawAddress::kEmpty;
+ } else {
+ p.peer_address = str2addr(env, peerAddress);
+ }
p.peer_address_type = peerAddressType;
p.discoverable = isDiscoverable;
return p;
diff --git a/android/app/jni/com_android_bluetooth_hfp.cpp b/android/app/jni/com_android_bluetooth_hfp.cpp
index 18a0bf1950..f321497e16 100644
--- a/android/app/jni/com_android_bluetooth_hfp.cpp
+++ b/android/app/jni/com_android_bluetooth_hfp.cpp
@@ -651,7 +651,8 @@ static jboolean isVoiceRecognitionSupportedNative(JNIEnv* env, jobject /* object
return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}
-static jboolean startVoiceRecognitionNative(JNIEnv* env, jobject /* object */, jbyteArray address) {
+static jboolean startVoiceRecognitionNative(JNIEnv* env, jobject /* object */, jbyteArray address,
+ jboolean sendResult) {
std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
if (!sBluetoothHfpInterface) {
log::warn("sBluetoothHfpInterface is null");
@@ -663,7 +664,7 @@ static jboolean startVoiceRecognitionNative(JNIEnv* env, jobject /* object */, j
jniThrowIOException(env, EINVAL);
return JNI_FALSE;
}
- bt_status_t status = sBluetoothHfpInterface->StartVoiceRecognition((RawAddress*)addr);
+ bt_status_t status = sBluetoothHfpInterface->StartVoiceRecognition((RawAddress*)addr, sendResult);
if (status != BT_STATUS_SUCCESS) {
log::error("Failed to start voice recognition, status: {}", bt_status_text(status));
}
@@ -986,7 +987,7 @@ int register_com_android_bluetooth_hfp(JNIEnv* env) {
{"disconnectAudioNative", "([B)Z", (void*)disconnectAudioNative},
{"isNoiseReductionSupportedNative", "([B)Z", (void*)isNoiseReductionSupportedNative},
{"isVoiceRecognitionSupportedNative", "([B)Z", (void*)isVoiceRecognitionSupportedNative},
- {"startVoiceRecognitionNative", "([B)Z", (void*)startVoiceRecognitionNative},
+ {"startVoiceRecognitionNative", "([BZ)Z", (void*)startVoiceRecognitionNative},
{"stopVoiceRecognitionNative", "([B)Z", (void*)stopVoiceRecognitionNative},
{"setVolumeNative", "(II[B)Z", (void*)setVolumeNative},
{"notifyDeviceStatusNative", "(IIII[B)Z", (void*)notifyDeviceStatusNative},
diff --git a/android/app/res/values-as/strings.xml b/android/app/res/values-as/strings.xml
index 2776941946..c53ee123e2 100644
--- a/android/app/res/values-as/strings.xml
+++ b/android/app/res/values-as/strings.xml
@@ -35,7 +35,7 @@
<string name="incoming_file_confirm_content" msgid="6573502088511901157">"অন্তৰ্গামী ফাইল গ্ৰহণ কৰিবনে?"</string>
<string name="incoming_file_confirm_cancel" msgid="9205906062663982692">"প্ৰত্যাখ্যান কৰক"</string>
<string name="incoming_file_confirm_ok" msgid="5046926299036238623">"গ্ৰহণ কৰক"</string>
- <string name="incoming_file_confirm_timeout_ok" msgid="8612187577686515660">"ঠিক"</string>
+ <string name="incoming_file_confirm_timeout_ok" msgid="8612187577686515660">"ঠিক আছে"</string>
<string name="incoming_file_confirm_timeout_content" msgid="3221412098281076974">"\"<xliff:g id="SENDER">%1$s</xliff:g>\"ৰ পৰা লাভ কৰা ফাইলটো গ্ৰহণ কৰোঁতে সময় ওকলিছে"</string>
<string name="incoming_file_confirm_Notification_title" msgid="5381395500920804895">"অন্তৰ্গামী ফাইল"</string>
<string name="incoming_file_confirm_Notification_content" msgid="2669135531488877921">"<xliff:g id="SENDER">%1$s</xliff:g> এটা ফাইল পঠিয়াবলৈ সাজু: <xliff:g id="FILE">%2$s</xliff:g>"</string>
@@ -58,18 +58,18 @@
<string name="download_fail_line1" msgid="3149552664349685007">"ফাইল লাভ কৰা নহ\'ল"</string>
<string name="download_fail_line2" msgid="4289018531070750414">"ফাইল: <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="download_fail_line3" msgid="2214989413171231684">"কাৰণ: <xliff:g id="REASON">%1$s</xliff:g>"</string>
- <string name="download_fail_ok" msgid="3272322648250767032">"ঠিক"</string>
+ <string name="download_fail_ok" msgid="3272322648250767032">"ঠিক আছে"</string>
<string name="download_succ_line5" msgid="1720346308221503270">"ফাইল লাভ কৰা হ’ল"</string>
<string name="download_succ_ok" msgid="7488662808922799824">"খোলক"</string>
<string name="upload_line1" msgid="1912803923255989287">"প্ৰতি: \"<xliff:g id="RECIPIENT">%1$s</xliff:g>\""</string>
<string name="upload_line3" msgid="5964902647036741603">"ফাইলৰ প্ৰকাৰ: <xliff:g id="TYPE">%1$s</xliff:g> (<xliff:g id="SIZE">%2$s</xliff:g>)"</string>
<string name="upload_line5" msgid="3477751464103201364">"ফাইল প্ৰেৰণ কৰি থকা হৈছে…"</string>
<string name="upload_succ_line5" msgid="165979135931118211">"ফাইল প্ৰেৰণ কৰা হ’ল"</string>
- <string name="upload_succ_ok" msgid="6797291708604959167">"ঠিক"</string>
+ <string name="upload_succ_ok" msgid="6797291708604959167">"ঠিক আছে"</string>
<string name="upload_fail_line1" msgid="7044307783071776426">"\"<xliff:g id="RECIPIENT">%1$s</xliff:g>\"লৈ ফাইলটো পঠিয়াব পৰা নগ\'ল।"</string>
<string name="upload_fail_line1_2" msgid="6102642590057711459">"ফাইল: <xliff:g id="FILE">%1$s</xliff:g>"</string>
<string name="upload_fail_cancel" msgid="1632528037932779727">"বন্ধ কৰক"</string>
- <string name="bt_error_btn_ok" msgid="2802751202009957372">"ঠিক"</string>
+ <string name="bt_error_btn_ok" msgid="2802751202009957372">"ঠিক আছে"</string>
<string name="unknown_file" msgid="3719981572107052685">"অজ্ঞাত ফাইল"</string>
<string name="unknown_file_desc" msgid="9185609398960437760">"এইধৰণৰ ফাইল পৰিচালনা কৰিবলৈ কোনো এপ্ নাই। \n"</string>
<string name="not_exist_file" msgid="5097565588949092486">"কোনো ফাইল নাই"</string>
diff --git a/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java b/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java
index d4fc9d54e8..a4c265adf7 100644
--- a/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java
+++ b/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java
@@ -306,4 +306,9 @@ public class BluetoothMethodProxy {
ComponentCaller caller, Uri uri, int modeFlags) {
return caller.checkContentUriPermission(uri, modeFlags);
}
+
+ /** Proxies {@link Context#grantUriPermission(String, Uri, int)}. } */
+ public void grantUriPermission(Context context, String packageName, Uri uri, int modeFlags) {
+ context.grantUriPermission(packageName, uri, modeFlags);
+ }
}
diff --git a/android/app/src/com/android/bluetooth/BluetoothObexTransport.java b/android/app/src/com/android/bluetooth/BluetoothObexTransport.java
index 3c57ec1600..d101f1736e 100644
--- a/android/app/src/com/android/bluetooth/BluetoothObexTransport.java
+++ b/android/app/src/com/android/bluetooth/BluetoothObexTransport.java
@@ -18,7 +18,6 @@ package com.android.bluetooth;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothSocket;
-import com.android.bluetooth.flags.Flags;
import com.android.obex.ObexTransport;
import java.io.DataInputStream;
@@ -112,10 +111,7 @@ public class BluetoothObexTransport implements ObexTransport {
if (mSocket == null) {
return null;
}
- String identityAddress =
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getBrEdrAddress(mSocket.getRemoteDevice())
- : mSocket.getRemoteDevice().getIdentityAddress();
+ String identityAddress = Utils.getBrEdrAddress(mSocket.getRemoteDevice());
return mSocket.getConnectionType() == BluetoothSocket.TYPE_RFCOMM
? identityAddress
: mSocket.getRemoteDevice().getAddress();
diff --git a/android/app/src/com/android/bluetooth/Utils.java b/android/app/src/com/android/bluetooth/Utils.java
index ce23339f0b..3a681bb7e7 100644
--- a/android/app/src/com/android/bluetooth/Utils.java
+++ b/android/app/src/com/android/bluetooth/Utils.java
@@ -624,6 +624,13 @@ public final class Utils {
return checkPermissionForDataDelivery(context, BLUETOOTH_CONNECT, source, message);
}
+ @SuppressLint("AndroidFrameworkRequiresPermission") // This method enforce the permission
+ @RequiresPermission(BLUETOOTH_CONNECT)
+ public static boolean checkConnectPermissionForDataDelivery(
+ Context context, AttributionSource source, String tag, String method) {
+ return checkConnectPermissionForDataDelivery(context, source, tag + "." + method + "()");
+ }
+
/**
* Returns true if the BLUETOOTH_SCAN permission is granted for the calling app. Returns false
* if the result is a soft denial. Throws SecurityException if the result is a hard denial.
@@ -646,8 +653,9 @@ public final class Utils {
@SuppressLint("AndroidFrameworkRequiresPermission") // This method enforce the permission
@RequiresPermission(BLUETOOTH_SCAN)
public static boolean checkScanPermissionForDataDelivery(
- Context context, AttributionSource source, String message) {
- return checkPermissionForDataDelivery(context, BLUETOOTH_SCAN, source, message);
+ Context context, AttributionSource source, String tag, String method) {
+ return checkPermissionForDataDelivery(
+ context, BLUETOOTH_SCAN, source, tag + "." + method + "()");
}
/**
diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpNativeInterface.java b/android/app/src/com/android/bluetooth/a2dp/A2dpNativeInterface.java
index fe74b2facd..688f57ce8a 100644
--- a/android/app/src/com/android/bluetooth/a2dp/A2dpNativeInterface.java
+++ b/android/app/src/com/android/bluetooth/a2dp/A2dpNativeInterface.java
@@ -29,8 +29,6 @@ import android.bluetooth.BluetoothCodecType;
import android.bluetooth.BluetoothDevice;
import com.android.bluetooth.Utils;
-import com.android.bluetooth.btservice.AdapterService;
-import com.android.bluetooth.flags.Flags;
import com.android.internal.annotations.VisibleForTesting;
import java.lang.annotation.Native;
@@ -41,15 +39,12 @@ import java.util.List;
public class A2dpNativeInterface {
private static final String TAG = A2dpNativeInterface.class.getSimpleName();
- private final AdapterService mAdapterService;
@Native private final A2dpNativeCallback mNativeCallback;
private BluetoothCodecType[] mSupportedCodecTypes;
@VisibleForTesting
- A2dpNativeInterface(
- @NonNull AdapterService adapterService, @NonNull A2dpNativeCallback nativeCallback) {
- mAdapterService = requireNonNull(adapterService);
+ A2dpNativeInterface(@NonNull A2dpNativeCallback nativeCallback) {
mNativeCallback = requireNonNull(nativeCallback);
}
@@ -132,15 +127,11 @@ public class A2dpNativeInterface {
return setCodecConfigPreferenceNative(getByteAddress(device), codecConfigArray);
}
- private byte[] getByteAddress(BluetoothDevice device) {
+ private static byte[] getByteAddress(BluetoothDevice device) {
if (device == null) {
return Utils.getBytesFromAddress("00:00:00:00:00:00");
}
- if (Flags.identityAddressNullIfNotKnown()) {
- return Utils.getByteBrEdrAddress(device);
- } else {
- return mAdapterService.getByteIdentityAddress(device);
- }
+ return Utils.getByteBrEdrAddress(device);
}
private native void initNative(
diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpService.java b/android/app/src/com/android/bluetooth/a2dp/A2dpService.java
index 9481146d61..6633e4e2ea 100644
--- a/android/app/src/com/android/bluetooth/a2dp/A2dpService.java
+++ b/android/app/src/com/android/bluetooth/a2dp/A2dpService.java
@@ -26,8 +26,6 @@ import static android.bluetooth.BluetoothProfile.STATE_CONNECTING;
import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTING;
-import static com.android.bluetooth.Utils.checkCallerTargetSdk;
-
import static java.util.Objects.requireNonNull;
import static java.util.Objects.requireNonNullElseGet;
@@ -44,15 +42,12 @@ import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.BufferConstraints;
-import android.bluetooth.IBluetoothA2dp;
import android.companion.CompanionDeviceManager;
-import android.content.AttributionSource;
import android.content.Intent;
import android.media.AudioDeviceCallback;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.media.BluetoothProfileConnectionInfo;
-import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -63,7 +58,6 @@ import com.android.bluetooth.BluetoothStatsLog;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.ActiveDeviceManager;
import com.android.bluetooth.btservice.AdapterService;
-import com.android.bluetooth.btservice.MetricsLogger;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.btservice.ServiceFactory;
import com.android.bluetooth.btservice.storage.DatabaseManager;
@@ -73,7 +67,6 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
@@ -132,7 +125,6 @@ public class A2dpService extends ProfileService {
nativeInterface,
() ->
new A2dpNativeInterface(
- adapterService,
new A2dpNativeCallback(adapterService, this)));
mDatabaseManager = requireNonNull(mAdapterService.getDatabase());
mAudioManager = requireNonNull(getSystemService(AudioManager.class));
@@ -168,7 +160,7 @@ public class A2dpService extends ProfileService {
@Override
protected IProfileServiceBinder initBinder() {
- return new BluetoothA2dpBinder(this);
+ return new A2dpServiceBinder(this);
}
@Override
@@ -203,6 +195,10 @@ public class A2dpService extends ProfileService {
mHandler.removeCallbacksAndMessages(null);
}
+ CompanionDeviceManager getCompanionDeviceManager() {
+ return mCompanionDeviceManager;
+ }
+
public static synchronized A2dpService getA2dpService() {
if (sA2dpService == null) {
Log.w(TAG, "getA2dpService(): service is null");
@@ -1001,13 +997,7 @@ public class A2dpService extends ProfileService {
return null;
}
Log.d(TAG, "Creating a new state machine for " + device);
- sm =
- new A2dpStateMachine(
- this,
- device,
- mNativeInterface,
- mA2dpOffloadEnabled,
- mLooper);
+ sm = new A2dpStateMachine(this, device, mNativeInterface, mA2dpOffloadEnabled, mLooper);
mStateMachines.put(device, sm);
return sm;
}
@@ -1345,320 +1335,6 @@ public class A2dpService extends ProfileService {
: null;
}
- /** Binder object: must be a static class or memory leak may occur. */
- @VisibleForTesting
- static class BluetoothA2dpBinder extends IBluetoothA2dp.Stub implements IProfileServiceBinder {
- private A2dpService mService;
-
- @RequiresPermission(BLUETOOTH_CONNECT)
- private A2dpService getServiceAndEnforceConnect(AttributionSource source) {
- // Cache mService because it can change while getService is called
- A2dpService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
- return service;
- }
-
- private A2dpService getService() {
- // Cache mService because it can change while getService is called
- A2dpService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)) {
- return null;
- }
- return service;
- }
-
- BluetoothA2dpBinder(A2dpService svc) {
- mService = svc;
- }
-
- @Override
- public void cleanup() {
- mService = null;
- }
-
- @Override
- public boolean connect(BluetoothDevice device, AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return false;
- }
-
- return service.connect(device);
- }
-
- @Override
- public boolean disconnect(BluetoothDevice device, AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return false;
- }
-
- return service.disconnect(device);
- }
-
- @Override
- public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- return service.getConnectedDevices();
- }
-
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(
- int[] states, AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- return service.getDevicesMatchingConnectionStates(states);
- }
-
- @Override
- public int getConnectionState(BluetoothDevice device, AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return STATE_DISCONNECTED;
- }
-
- return service.getConnectionState(device);
- }
-
- @Override
- public boolean setActiveDevice(BluetoothDevice device, AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return false;
- }
-
- if (device == null) {
- return service.removeActiveDevice(false);
- } else {
- return service.setActiveDevice(device);
- }
- }
-
- @Override
- public BluetoothDevice getActiveDevice(AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return null;
- }
-
- return service.getActiveDevice();
- }
-
- @Override
- public boolean setConnectionPolicy(
- BluetoothDevice device, int connectionPolicy, AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.setConnectionPolicy(device, connectionPolicy);
- }
-
- @Override
- public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return CONNECTION_POLICY_UNKNOWN;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getConnectionPolicy(device);
- }
-
- @Override
- public void setAvrcpAbsoluteVolume(int volume, AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- service.setAvrcpAbsoluteVolume(volume);
- }
-
- @Override
- public boolean isA2dpPlaying(BluetoothDevice device, AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return false;
- }
-
- return service.isA2dpPlaying(device);
- }
-
- @Override
- public List<BluetoothCodecType> getSupportedCodecTypes() {
- A2dpService service = getService();
- if (service == null) {
- return Collections.emptyList();
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getSupportedCodecTypes();
- }
-
- @Override
- public BluetoothCodecStatus getCodecStatus(
- BluetoothDevice device, AttributionSource source) {
- requireNonNull(device);
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return null;
- }
-
- Utils.enforceCdmAssociationIfNotBluetoothPrivileged(
- service, service.mCompanionDeviceManager, source, device);
-
- return service.getCodecStatus(device);
- }
-
- @Override
- public void setCodecConfigPreference(
- BluetoothDevice device,
- BluetoothCodecConfig codecConfig,
- AttributionSource source) {
- requireNonNull(device);
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return;
- }
-
- Utils.enforceCdmAssociationIfNotBluetoothPrivileged(
- service, service.mCompanionDeviceManager, source, device);
-
- service.setCodecConfigPreference(device, codecConfig);
- }
-
- @Override
- public void enableOptionalCodecs(BluetoothDevice device, AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return;
- }
-
- if (checkCallerTargetSdk(
- mService, source.getPackageName(), Build.VERSION_CODES.TIRAMISU)) {
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- }
- service.enableOptionalCodecs(device);
- }
-
- @Override
- public void disableOptionalCodecs(BluetoothDevice device, AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return;
- }
-
- if (checkCallerTargetSdk(
- mService, source.getPackageName(), Build.VERSION_CODES.TIRAMISU)) {
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- }
- service.disableOptionalCodecs(device);
- }
-
- @Override
- public int isOptionalCodecsSupported(BluetoothDevice device, AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN;
- }
-
- if (checkCallerTargetSdk(
- mService, source.getPackageName(), Build.VERSION_CODES.TIRAMISU)) {
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- }
- return service.getSupportsOptionalCodecs(device);
- }
-
- @Override
- public int isOptionalCodecsEnabled(BluetoothDevice device, AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN;
- }
-
- if (checkCallerTargetSdk(
- mService, source.getPackageName(), Build.VERSION_CODES.TIRAMISU)) {
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- }
- return service.getOptionalCodecsEnabled(device);
- }
-
- @Override
- public void setOptionalCodecsEnabled(
- BluetoothDevice device, int value, AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return;
- }
-
- if (checkCallerTargetSdk(
- mService, source.getPackageName(), Build.VERSION_CODES.TIRAMISU)) {
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- }
- service.setOptionalCodecsEnabled(device, value);
- }
-
- @Override
- public int getDynamicBufferSupport(AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return BluetoothA2dp.DYNAMIC_BUFFER_SUPPORT_NONE;
- }
-
- return service.getDynamicBufferSupport();
- }
-
- @Override
- public BufferConstraints getBufferConstraints(AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return null;
- }
-
- return service.getBufferConstraints();
- }
-
- @Override
- public boolean setBufferLengthMillis(int codec, int value, AttributionSource source) {
- A2dpService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return false;
- }
-
- return service.setBufferLengthMillis(codec, value);
- }
- }
-
@Override
public void dump(StringBuilder sb) {
super.dump(sb);
diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpServiceBinder.java b/android/app/src/com/android/bluetooth/a2dp/A2dpServiceBinder.java
new file mode 100644
index 0000000000..da8aaae42a
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/a2dp/A2dpServiceBinder.java
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.a2dp;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+
+import static com.android.bluetooth.Utils.checkCallerTargetSdk;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.RequiresPermission;
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothCodecConfig;
+import android.bluetooth.BluetoothCodecStatus;
+import android.bluetooth.BluetoothCodecType;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BufferConstraints;
+import android.bluetooth.IBluetoothA2dp;
+import android.content.AttributionSource;
+import android.os.Build;
+
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+
+import java.util.Collections;
+import java.util.List;
+
+class A2dpServiceBinder extends IBluetoothA2dp.Stub implements IProfileServiceBinder {
+ private static final String TAG = A2dpServiceBinder.class.getSimpleName();
+
+ private A2dpService mService;
+
+ A2dpServiceBinder(A2dpService svc) {
+ mService = svc;
+ }
+
+ @Override
+ public void cleanup() {
+ mService = null;
+ }
+
+ private A2dpService getService() {
+ A2dpService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)) {
+ return null;
+ }
+ return service;
+ }
+
+ @RequiresPermission(BLUETOOTH_CONNECT)
+ private A2dpService getServiceAndEnforceConnect(AttributionSource source) {
+ A2dpService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
+ || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
+ return null;
+ }
+ return service;
+ }
+
+ @Override
+ public boolean connect(BluetoothDevice device, AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return false;
+ }
+ return service.connect(device);
+ }
+
+ @Override
+ public boolean disconnect(BluetoothDevice device, AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return false;
+ }
+ return service.disconnect(device);
+ }
+
+ @Override
+ public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getConnectedDevices();
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ int[] states, AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getDevicesMatchingConnectionStates(states);
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice device, AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return STATE_DISCONNECTED;
+ }
+ return service.getConnectionState(device);
+ }
+
+ @Override
+ public boolean setActiveDevice(BluetoothDevice device, AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return false;
+ }
+
+ if (device == null) {
+ return service.removeActiveDevice(false);
+ } else {
+ return service.setActiveDevice(device);
+ }
+ }
+
+ @Override
+ public BluetoothDevice getActiveDevice(AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return null;
+ }
+ return service.getActiveDevice();
+ }
+
+ @Override
+ public boolean setConnectionPolicy(
+ BluetoothDevice device, int connectionPolicy, AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.setConnectionPolicy(device, connectionPolicy);
+ }
+
+ @Override
+ public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return CONNECTION_POLICY_UNKNOWN;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getConnectionPolicy(device);
+ }
+
+ @Override
+ public void setAvrcpAbsoluteVolume(int volume, AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.setAvrcpAbsoluteVolume(volume);
+ }
+
+ @Override
+ public boolean isA2dpPlaying(BluetoothDevice device, AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return false;
+ }
+ return service.isA2dpPlaying(device);
+ }
+
+ @Override
+ public List<BluetoothCodecType> getSupportedCodecTypes() {
+ A2dpService service = getService();
+ if (service == null) {
+ return Collections.emptyList();
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getSupportedCodecTypes();
+ }
+
+ @Override
+ public BluetoothCodecStatus getCodecStatus(BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return null;
+ }
+
+ Utils.enforceCdmAssociationIfNotBluetoothPrivileged(
+ service, service.getCompanionDeviceManager(), source, device);
+
+ return service.getCodecStatus(device);
+ }
+
+ @Override
+ public void setCodecConfigPreference(
+ BluetoothDevice device, BluetoothCodecConfig codecConfig, AttributionSource source) {
+ requireNonNull(device);
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return;
+ }
+
+ Utils.enforceCdmAssociationIfNotBluetoothPrivileged(
+ service, service.getCompanionDeviceManager(), source, device);
+
+ service.setCodecConfigPreference(device, codecConfig);
+ }
+
+ @Override
+ public void enableOptionalCodecs(BluetoothDevice device, AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return;
+ }
+
+ if (checkCallerTargetSdk(mService, source.getPackageName(), Build.VERSION_CODES.TIRAMISU)) {
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ }
+ service.enableOptionalCodecs(device);
+ }
+
+ @Override
+ public void disableOptionalCodecs(BluetoothDevice device, AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return;
+ }
+
+ if (checkCallerTargetSdk(mService, source.getPackageName(), Build.VERSION_CODES.TIRAMISU)) {
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ }
+ service.disableOptionalCodecs(device);
+ }
+
+ @Override
+ public int isOptionalCodecsSupported(BluetoothDevice device, AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN;
+ }
+
+ if (checkCallerTargetSdk(mService, source.getPackageName(), Build.VERSION_CODES.TIRAMISU)) {
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ }
+ return service.getSupportsOptionalCodecs(device);
+ }
+
+ @Override
+ public int isOptionalCodecsEnabled(BluetoothDevice device, AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN;
+ }
+
+ if (checkCallerTargetSdk(mService, source.getPackageName(), Build.VERSION_CODES.TIRAMISU)) {
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ }
+ return service.getOptionalCodecsEnabled(device);
+ }
+
+ @Override
+ public void setOptionalCodecsEnabled(
+ BluetoothDevice device, int value, AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return;
+ }
+
+ if (checkCallerTargetSdk(mService, source.getPackageName(), Build.VERSION_CODES.TIRAMISU)) {
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ }
+ service.setOptionalCodecsEnabled(device, value);
+ }
+
+ @Override
+ public int getDynamicBufferSupport(AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return BluetoothA2dp.DYNAMIC_BUFFER_SUPPORT_NONE;
+ }
+
+ return service.getDynamicBufferSupport();
+ }
+
+ @Override
+ public BufferConstraints getBufferConstraints(AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return null;
+ }
+
+ return service.getBufferConstraints();
+ }
+
+ @Override
+ public boolean setBufferLengthMillis(int codec, int value, AttributionSource source) {
+ A2dpService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return false;
+ }
+
+ return service.setBufferLengthMillis(codec, value);
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkNativeInterface.java b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkNativeInterface.java
index e3b4c400a3..6822e4e734 100644
--- a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkNativeInterface.java
+++ b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkNativeInterface.java
@@ -23,7 +23,6 @@ import android.util.Log;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AdapterService;
-import com.android.bluetooth.flags.Flags;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -78,14 +77,6 @@ public class A2dpSinkNativeInterface {
return mAdapterService.getDeviceFromByte(address);
}
- private byte[] getByteAddress(BluetoothDevice device) {
- if (Flags.identityAddressNullIfNotKnown()) {
- return Utils.getByteBrEdrAddress(device);
- } else {
- return mAdapterService.getByteIdentityAddress(device);
- }
- }
-
/**
* Initiates an A2DP connection to a remote device.
*
@@ -93,7 +84,7 @@ public class A2dpSinkNativeInterface {
* @return true on success, otherwise false.
*/
public boolean connectA2dpSink(BluetoothDevice device) {
- return connectA2dpNative(getByteAddress(device));
+ return connectA2dpNative(Utils.getByteBrEdrAddress(device));
}
/**
@@ -103,7 +94,7 @@ public class A2dpSinkNativeInterface {
* @return true on success, otherwise false.
*/
public boolean disconnectA2dpSink(BluetoothDevice device) {
- return disconnectA2dpNative(getByteAddress(device));
+ return disconnectA2dpNative(Utils.getByteBrEdrAddress(device));
}
/**
@@ -120,7 +111,7 @@ public class A2dpSinkNativeInterface {
// Translate to byte address for JNI. Use an all 0 MAC for no active device
byte[] address = null;
if (device != null) {
- address = getByteAddress(device);
+ address = Utils.getByteBrEdrAddress(device);
} else {
address = Utils.getBytesFromAddress("00:00:00:00:00:00");
}
diff --git a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java
index 10b9249bad..6750a9a9c8 100644
--- a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java
+++ b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java
@@ -13,30 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.bluetooth.a2dpsink;
-import static android.Manifest.permission.BLUETOOTH_CONNECT;
-import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTING;
import static java.util.Objects.requireNonNull;
-import android.annotation.RequiresPermission;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothAudioConfig;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
-import android.bluetooth.IBluetoothA2dpSink;
-import android.content.AttributionSource;
import android.os.Looper;
import android.sysprop.BluetoothProperties;
import android.util.Log;
-import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.btservice.storage.DatabaseManager;
@@ -45,7 +39,6 @@ import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -177,136 +170,6 @@ public class A2dpSinkService extends ProfileService {
return new A2dpSinkServiceBinder(this);
}
- // Binder object: Must be static class or memory leak may occur
- @VisibleForTesting
- static class A2dpSinkServiceBinder extends IBluetoothA2dpSink.Stub
- implements IProfileServiceBinder {
- private A2dpSinkService mService;
-
- A2dpSinkServiceBinder(A2dpSinkService svc) {
- mService = svc;
- }
-
- @Override
- public void cleanup() {
- mService = null;
- }
-
- @RequiresPermission(BLUETOOTH_CONNECT)
- private A2dpSinkService getService(AttributionSource source) {
- // Cache mService because it can change while getService is called
- A2dpSinkService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
-
- return service;
- }
-
- @Override
- public boolean connect(BluetoothDevice device, AttributionSource source) {
- A2dpSinkService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.connect(device);
- }
-
- @Override
- public boolean disconnect(BluetoothDevice device, AttributionSource source) {
- A2dpSinkService service = getService(source);
- if (service == null) {
- return false;
- }
- return service.disconnect(device);
- }
-
- @Override
- public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
- A2dpSinkService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
- return service.getConnectedDevices();
- }
-
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(
- int[] states, AttributionSource source) {
- A2dpSinkService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
- return service.getDevicesMatchingConnectionStates(states);
- }
-
- @Override
- public int getConnectionState(BluetoothDevice device, AttributionSource source) {
- A2dpSinkService service = getService(source);
- if (service == null) {
- return STATE_DISCONNECTED;
- }
- return service.getConnectionState(device);
- }
-
- @Override
- public boolean setConnectionPolicy(
- BluetoothDevice device, int connectionPolicy, AttributionSource source) {
- A2dpSinkService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.setConnectionPolicy(device, connectionPolicy);
- }
-
- @Override
- public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
- A2dpSinkService service = getService(source);
- if (service == null) {
- return CONNECTION_POLICY_UNKNOWN;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getConnectionPolicy(device);
- }
-
- @Override
- public boolean isA2dpPlaying(BluetoothDevice device, AttributionSource source) {
- A2dpSinkService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.isA2dpPlaying(device);
- }
-
- @Override
- public BluetoothAudioConfig getAudioConfig(
- BluetoothDevice device, AttributionSource source) {
- A2dpSinkService service = getService(source);
- if (service == null) {
- return null;
- }
- return service.getAudioConfig(device);
- }
- }
-
/* Generic Profile Code */
/**
diff --git a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceBinder.java b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceBinder.java
new file mode 100644
index 0000000000..851e48a286
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceBinder.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.a2dpsink;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+
+import android.annotation.RequiresPermission;
+import android.bluetooth.BluetoothAudioConfig;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.IBluetoothA2dpSink;
+import android.content.AttributionSource;
+
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+
+import java.util.Collections;
+import java.util.List;
+
+class A2dpSinkServiceBinder extends IBluetoothA2dpSink.Stub implements IProfileServiceBinder {
+ private static final String TAG = A2dpSinkServiceBinder.class.getSimpleName();
+
+ private A2dpSinkService mService;
+
+ A2dpSinkServiceBinder(A2dpSinkService svc) {
+ mService = svc;
+ }
+
+ @Override
+ public void cleanup() {
+ mService = null;
+ }
+
+ @RequiresPermission(BLUETOOTH_CONNECT)
+ private A2dpSinkService getService(AttributionSource source) {
+ A2dpSinkService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
+ || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
+ return null;
+ }
+
+ return service;
+ }
+
+ @Override
+ public boolean connect(BluetoothDevice device, AttributionSource source) {
+ A2dpSinkService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.connect(device);
+ }
+
+ @Override
+ public boolean disconnect(BluetoothDevice device, AttributionSource source) {
+ A2dpSinkService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.disconnect(device);
+ }
+
+ @Override
+ public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
+ A2dpSinkService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getConnectedDevices();
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ int[] states, AttributionSource source) {
+ A2dpSinkService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getDevicesMatchingConnectionStates(states);
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice device, AttributionSource source) {
+ A2dpSinkService service = getService(source);
+ if (service == null) {
+ return STATE_DISCONNECTED;
+ }
+ return service.getConnectionState(device);
+ }
+
+ @Override
+ public boolean setConnectionPolicy(
+ BluetoothDevice device, int connectionPolicy, AttributionSource source) {
+ A2dpSinkService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.setConnectionPolicy(device, connectionPolicy);
+ }
+
+ @Override
+ public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
+ A2dpSinkService service = getService(source);
+ if (service == null) {
+ return CONNECTION_POLICY_UNKNOWN;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getConnectionPolicy(device);
+ }
+
+ @Override
+ public boolean isA2dpPlaying(BluetoothDevice device, AttributionSource source) {
+ A2dpSinkService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.isA2dpPlaying(device);
+ }
+
+ @Override
+ public BluetoothAudioConfig getAudioConfig(BluetoothDevice device, AttributionSource source) {
+ A2dpSinkService service = getService(source);
+ if (service == null) {
+ return null;
+ }
+ return service.getAudioConfig(device);
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/a2dpsink/OWNERS b/android/app/src/com/android/bluetooth/a2dpsink/OWNERS
deleted file mode 100644
index ecd59038a1..0000000000
--- a/android/app/src/com/android/bluetooth/a2dpsink/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_automotive
diff --git a/android/app/src/com/android/bluetooth/audio_util/MediaBrowserWrapper.java b/android/app/src/com/android/bluetooth/audio_util/MediaBrowserWrapper.java
index 517e810d8a..3c235cce76 100644
--- a/android/app/src/com/android/bluetooth/audio_util/MediaBrowserWrapper.java
+++ b/android/app/src/com/android/bluetooth/audio_util/MediaBrowserWrapper.java
@@ -197,7 +197,7 @@ class MediaBrowserWrapper {
mSubscribedIds.put(
rootId, new ArrayList<>(Arrays.asList(callback)));
mWrappedBrowser.subscribe(
- rootId, new BrowserSubscriptionCallback(mediaId));
+ rootId, new BrowserSubscriptionCallback(rootId));
});
} else {
mSubscribedIds.put(mediaId, new ArrayList<>(Arrays.asList(callback)));
diff --git a/android/app/src/com/android/bluetooth/avrcp/AvrcpNativeInterface.java b/android/app/src/com/android/bluetooth/avrcp/AvrcpNativeInterface.java
index 720ce84dd8..85d1043023 100644
--- a/android/app/src/com/android/bluetooth/avrcp/AvrcpNativeInterface.java
+++ b/android/app/src/com/android/bluetooth/avrcp/AvrcpNativeInterface.java
@@ -28,7 +28,6 @@ import com.android.bluetooth.audio_util.PlayStatus;
import com.android.bluetooth.audio_util.PlayerInfo;
import com.android.bluetooth.audio_util.PlayerSettingsManager.PlayerSettingsValues;
import com.android.bluetooth.btservice.AdapterService;
-import com.android.bluetooth.flags.Flags;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -93,10 +92,7 @@ public class AvrcpNativeInterface {
}
void setBipClientStatus(BluetoothDevice device, boolean connected) {
- String identityAddress =
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getBrEdrAddress(device)
- : mAdapterService.getIdentityAddress(device.getAddress());
+ String identityAddress = Utils.getBrEdrAddress(device);
setBipClientStatusNative(identityAddress, connected);
}
@@ -237,10 +233,7 @@ public class AvrcpNativeInterface {
}
boolean disconnectDevice(BluetoothDevice device) {
- String identityAddress =
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getBrEdrAddress(device)
- : mAdapterService.getIdentityAddress(device.getAddress());
+ String identityAddress = Utils.getBrEdrAddress(device);
d("disconnectDevice: identityAddress=" + identityAddress);
return disconnectDeviceNative(identityAddress);
}
@@ -278,10 +271,7 @@ public class AvrcpNativeInterface {
void sendVolumeChanged(BluetoothDevice device, int volume) {
d("sendVolumeChanged: volume=" + volume);
- String identityAddress =
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getBrEdrAddress(device)
- : mAdapterService.getIdentityAddress(device.getAddress());
+ String identityAddress = Utils.getBrEdrAddress(device);
sendVolumeChangedNative(identityAddress, volume);
}
diff --git a/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java b/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java
index 4551f320da..c4ef6a2437 100644
--- a/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java
+++ b/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java
@@ -16,19 +16,14 @@
package com.android.bluetooth.avrcpcontroller;
-import static android.Manifest.permission.BLUETOOTH_CONNECT;
import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
import static android.bluetooth.BluetoothProfile.STATE_CONNECTING;
import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
import static java.util.Objects.requireNonNull;
-import android.annotation.RequiresPermission;
import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothAvrcpPlayerSettings;
import android.bluetooth.BluetoothDevice;
-import android.bluetooth.IBluetoothAvrcpController;
-import android.content.AttributionSource;
import android.content.Intent;
import android.media.AudioManager;
import android.support.v4.media.MediaBrowserCompat.MediaItem;
@@ -46,7 +41,6 @@ import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -368,90 +362,6 @@ public class AvrcpControllerService extends ProfileService {
return new AvrcpControllerServiceBinder(this);
}
- // Binder object: Must be static class or memory leak may occur
- @VisibleForTesting
- static class AvrcpControllerServiceBinder extends IBluetoothAvrcpController.Stub
- implements IProfileServiceBinder {
- private AvrcpControllerService mService;
-
- AvrcpControllerServiceBinder(AvrcpControllerService service) {
- mService = service;
- }
-
- @Override
- public void cleanup() {
- mService = null;
- }
-
- @RequiresPermission(BLUETOOTH_CONNECT)
- private AvrcpControllerService getService(AttributionSource source) {
- // Cache mService because it can change while getService is called
- AvrcpControllerService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
-
- return service;
- }
-
- @Override
- public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
- AvrcpControllerService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
- return service.getConnectedDevices();
- }
-
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(
- int[] states, AttributionSource source) {
- AvrcpControllerService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
- return service.getDevicesMatchingConnectionStates(states);
- }
-
- @Override
- public int getConnectionState(BluetoothDevice device, AttributionSource source) {
- AvrcpControllerService service = getService(source);
- if (service == null) {
- return STATE_DISCONNECTED;
- }
- return service.getConnectionState(device);
- }
-
- @Override
- public void sendGroupNavigationCmd(
- BluetoothDevice device, int keyCode, int keyState, AttributionSource source) {
- getService(source);
- Log.w(TAG, "sendGroupNavigationCmd not implemented");
- }
-
- @Override
- public void setPlayerApplicationSetting(
- BluetoothAvrcpPlayerSettings settings, AttributionSource source) {
- getService(source);
- Log.w(TAG, "setPlayerApplicationSetting not implemented");
- }
-
- @Override
- public BluetoothAvrcpPlayerSettings getPlayerSettings(
- BluetoothDevice device, AttributionSource source) {
- getService(source);
- Log.w(TAG, "getPlayerSettings not implemented");
- return null;
- }
- }
-
// Called by JNI when a device has connected or disconnected.
@VisibleForTesting
synchronized void onConnectionStateChanged(
diff --git a/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceBinder.java b/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceBinder.java
new file mode 100644
index 0000000000..105e9a8709
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceBinder.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.avrcpcontroller;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+
+import android.annotation.RequiresPermission;
+import android.bluetooth.BluetoothAvrcpPlayerSettings;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.IBluetoothAvrcpController;
+import android.content.AttributionSource;
+import android.util.Log;
+
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+
+import java.util.Collections;
+import java.util.List;
+
+class AvrcpControllerServiceBinder extends IBluetoothAvrcpController.Stub
+ implements IProfileServiceBinder {
+ private static final String TAG = AvrcpControllerServiceBinder.class.getSimpleName();
+
+ private AvrcpControllerService mService;
+
+ AvrcpControllerServiceBinder(AvrcpControllerService service) {
+ mService = service;
+ }
+
+ @Override
+ public void cleanup() {
+ mService = null;
+ }
+
+ @RequiresPermission(BLUETOOTH_CONNECT)
+ private AvrcpControllerService getService(AttributionSource source) {
+ AvrcpControllerService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
+ || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
+ return null;
+ }
+
+ return service;
+ }
+
+ @Override
+ public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
+ AvrcpControllerService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getConnectedDevices();
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ int[] states, AttributionSource source) {
+ AvrcpControllerService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getDevicesMatchingConnectionStates(states);
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice device, AttributionSource source) {
+ AvrcpControllerService service = getService(source);
+ if (service == null) {
+ return STATE_DISCONNECTED;
+ }
+ return service.getConnectionState(device);
+ }
+
+ @Override
+ public void sendGroupNavigationCmd(
+ BluetoothDevice device, int keyCode, int keyState, AttributionSource source) {
+ getService(source);
+ Log.w(TAG, "sendGroupNavigationCmd not implemented");
+ }
+
+ @Override
+ public void setPlayerApplicationSetting(
+ BluetoothAvrcpPlayerSettings settings, AttributionSource source) {
+ getService(source);
+ Log.w(TAG, "setPlayerApplicationSetting not implemented");
+ }
+
+ @Override
+ public BluetoothAvrcpPlayerSettings getPlayerSettings(
+ BluetoothDevice device, AttributionSource source) {
+ getService(source);
+ Log.w(TAG, "getPlayerSettings not implemented");
+ return null;
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/avrcpcontroller/OWNERS b/android/app/src/com/android/bluetooth/avrcpcontroller/OWNERS
deleted file mode 100644
index ecd59038a1..0000000000
--- a/android/app/src/com/android/bluetooth/avrcpcontroller/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_automotive
diff --git a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java
index 2b2b495ce4..42528676b4 100644
--- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java
+++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java
@@ -16,9 +16,6 @@
package com.android.bluetooth.bass_client;
-import static android.Manifest.permission.BLUETOOTH_CONNECT;
-import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
-import static android.Manifest.permission.BLUETOOTH_SCAN;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
@@ -36,7 +33,6 @@ import static com.android.bluetooth.flags.Flags.leaudioSortScansToSyncByFails;
import static java.util.Objects.requireNonNull;
-import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -50,7 +46,6 @@ import android.bluetooth.BluetoothLeBroadcastSubgroup;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
import android.bluetooth.BluetoothUuid;
-import android.bluetooth.IBluetoothLeBroadcastAssistant;
import android.bluetooth.IBluetoothLeBroadcastAssistantCallback;
import android.bluetooth.le.IScannerCallback;
import android.bluetooth.le.PeriodicAdvertisingCallback;
@@ -60,7 +55,6 @@ import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanRecord;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
-import android.content.AttributionSource;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -737,7 +731,7 @@ public class BassClientService extends ProfileService {
@Override
protected IProfileServiceBinder initBinder() {
- return new BluetoothLeBroadcastAssistantBinder(this);
+ return new BassClientServiceBinder(this);
}
@Override
@@ -4829,234 +4823,4 @@ public class BassClientService extends ProfileService {
sEventLogger.dump(sb);
sb.append("\n");
}
-
- /** Binder object: must be a static class or memory leak may occur */
- @VisibleForTesting
- static class BluetoothLeBroadcastAssistantBinder extends IBluetoothLeBroadcastAssistant.Stub
- implements IProfileServiceBinder {
- BassClientService mService;
-
- BluetoothLeBroadcastAssistantBinder(BassClientService svc) {
- mService = svc;
- }
-
- @Override
- public void cleanup() {
- mService = null;
- }
-
- @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED})
- private BassClientService getServiceAndEnforceConnect(AttributionSource source) {
- // Cache mService because it can change while getService is called
- BassClientService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service;
- }
-
- @RequiresPermission(allOf = {BLUETOOTH_SCAN, BLUETOOTH_PRIVILEGED})
- private BassClientService getServiceAndEnforceScan(AttributionSource source) {
- // Cache mService because it can change while getService is called
- BassClientService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
- || !Utils.checkScanPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service;
- }
-
- @Override
- public int getConnectionState(BluetoothDevice sink, AttributionSource source) {
- BassClientService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- Log.e(TAG, "Service is null");
- return STATE_DISCONNECTED;
- }
- return service.getConnectionState(sink);
- }
-
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(
- int[] states, AttributionSource source) {
- BassClientService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- Log.e(TAG, "Service is null");
- return Collections.emptyList();
- }
- return service.getDevicesMatchingConnectionStates(states);
- }
-
- @Override
- public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
- BassClientService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- Log.e(TAG, "Service is null");
- return Collections.emptyList();
- }
- return service.getConnectedDevices();
- }
-
- @Override
- public boolean setConnectionPolicy(
- BluetoothDevice device, int connectionPolicy, AttributionSource source) {
- BassClientService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- Log.e(TAG, "Service is null");
- return false;
- }
- return service.setConnectionPolicy(device, connectionPolicy);
- }
-
- @Override
- public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
- BassClientService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- Log.e(TAG, "Service is null");
- return CONNECTION_POLICY_FORBIDDEN;
- }
- return service.getConnectionPolicy(device);
- }
-
- @Override
- public void registerCallback(
- IBluetoothLeBroadcastAssistantCallback cb, AttributionSource source) {
- BassClientService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- Log.e(TAG, "Service is null");
- return;
- }
- service.registerCallback(cb);
- }
-
- @Override
- public void unregisterCallback(
- IBluetoothLeBroadcastAssistantCallback cb, AttributionSource source) {
- BassClientService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- Log.e(TAG, "Service is null");
- return;
- }
- service.unregisterCallback(cb);
- }
-
- @Override
- public void startSearchingForSources(List<ScanFilter> filters, AttributionSource source) {
- BassClientService service = getServiceAndEnforceScan(source);
- if (service == null) {
- Log.e(TAG, "Service is null");
- return;
- }
- service.startSearchingForSources(filters);
- }
-
- @Override
- public void stopSearchingForSources(AttributionSource source) {
- BassClientService service = getServiceAndEnforceScan(source);
- if (service == null) {
- Log.e(TAG, "Service is null");
- return;
- }
- service.stopSearchingForSources();
- }
-
- @Override
- public boolean isSearchInProgress(AttributionSource source) {
- BassClientService service = getServiceAndEnforceScan(source);
- if (service == null) {
- Log.e(TAG, "Service is null");
- return false;
- }
- return service.isSearchInProgress();
- }
-
- @Override
- public void addSource(
- BluetoothDevice sink,
- BluetoothLeBroadcastMetadata sourceMetadata,
- boolean isGroupOp,
- AttributionSource source) {
- BassClientService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- Log.e(TAG, "Service is null");
- return;
- }
- service.addSource(sink, sourceMetadata, isGroupOp);
- }
-
- @Override
- public void modifySource(
- BluetoothDevice sink,
- int sourceId,
- BluetoothLeBroadcastMetadata updatedMetadata,
- AttributionSource source) {
- BassClientService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- Log.e(TAG, "Service is null");
- return;
- }
- service.modifySource(sink, sourceId, updatedMetadata);
- }
-
- @Override
- public void removeSource(BluetoothDevice sink, int sourceId, AttributionSource source) {
- BassClientService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- Log.e(TAG, "Service is null");
- return;
- }
- service.removeSource(sink, sourceId);
- }
-
- @Override
- public List<BluetoothLeBroadcastReceiveState> getAllSources(
- BluetoothDevice sink, AttributionSource source) {
- BassClientService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- Log.e(TAG, "Service is null");
- return Collections.emptyList();
- }
- return service.getAllSources(sink);
- }
-
- @Override
- public int getMaximumSourceCapacity(BluetoothDevice sink, AttributionSource source) {
- BassClientService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- Log.e(TAG, "Service is null");
- return 0;
- }
- return service.getMaximumSourceCapacity(sink);
- }
-
- @Override
- public BluetoothLeBroadcastMetadata getSourceMetadata(
- BluetoothDevice sink, int sourceId, AttributionSource source) {
- BassClientService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- Log.e(TAG, "Service is null");
- return null;
- }
- return service.getSourceMetadata(sink, sourceId);
- }
- }
}
diff --git a/android/app/src/com/android/bluetooth/bass_client/BassClientServiceBinder.java b/android/app/src/com/android/bluetooth/bass_client/BassClientServiceBinder.java
new file mode 100644
index 0000000000..d319e6ed47
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/bass_client/BassClientServiceBinder.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.bass_client;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.Manifest.permission.BLUETOOTH_SCAN;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+
+import android.annotation.RequiresPermission;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.bluetooth.BluetoothLeBroadcastReceiveState;
+import android.bluetooth.IBluetoothLeBroadcastAssistant;
+import android.bluetooth.IBluetoothLeBroadcastAssistantCallback;
+import android.bluetooth.le.ScanFilter;
+import android.content.AttributionSource;
+import android.util.Log;
+
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+
+import java.util.Collections;
+import java.util.List;
+
+class BassClientServiceBinder extends IBluetoothLeBroadcastAssistant.Stub
+ implements IProfileServiceBinder {
+ private static final String TAG = BassClientServiceBinder.class.getSimpleName();
+
+ private BassClientService mService;
+
+ BassClientServiceBinder(BassClientService svc) {
+ mService = svc;
+ }
+
+ @Override
+ public void cleanup() {
+ mService = null;
+ }
+
+ @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED})
+ private BassClientService getServiceAndEnforceConnect(AttributionSource source) {
+ BassClientService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
+ || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
+ return null;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+
+ return service;
+ }
+
+ @RequiresPermission(allOf = {BLUETOOTH_SCAN, BLUETOOTH_PRIVILEGED})
+ private BassClientService getServiceAndEnforceScan(AttributionSource source) {
+ BassClientService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
+ || !Utils.checkScanPermissionForDataDelivery(
+ service, source, TAG, "getServiceAndEnforceScan")) {
+ return null;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+
+ return service;
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice sink, AttributionSource source) {
+ BassClientService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ Log.e(TAG, "Service is null");
+ return STATE_DISCONNECTED;
+ }
+ return service.getConnectionState(sink);
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ int[] states, AttributionSource source) {
+ BassClientService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ Log.e(TAG, "Service is null");
+ return Collections.emptyList();
+ }
+ return service.getDevicesMatchingConnectionStates(states);
+ }
+
+ @Override
+ public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
+ BassClientService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ Log.e(TAG, "Service is null");
+ return Collections.emptyList();
+ }
+ return service.getConnectedDevices();
+ }
+
+ @Override
+ public boolean setConnectionPolicy(
+ BluetoothDevice device, int connectionPolicy, AttributionSource source) {
+ BassClientService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ Log.e(TAG, "Service is null");
+ return false;
+ }
+ return service.setConnectionPolicy(device, connectionPolicy);
+ }
+
+ @Override
+ public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
+ BassClientService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ Log.e(TAG, "Service is null");
+ return CONNECTION_POLICY_FORBIDDEN;
+ }
+ return service.getConnectionPolicy(device);
+ }
+
+ @Override
+ public void registerCallback(
+ IBluetoothLeBroadcastAssistantCallback cb, AttributionSource source) {
+ BassClientService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ Log.e(TAG, "Service is null");
+ return;
+ }
+ service.registerCallback(cb);
+ }
+
+ @Override
+ public void unregisterCallback(
+ IBluetoothLeBroadcastAssistantCallback cb, AttributionSource source) {
+ BassClientService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ Log.e(TAG, "Service is null");
+ return;
+ }
+ service.unregisterCallback(cb);
+ }
+
+ @Override
+ public void startSearchingForSources(List<ScanFilter> filters, AttributionSource source) {
+ BassClientService service = getServiceAndEnforceScan(source);
+ if (service == null) {
+ Log.e(TAG, "Service is null");
+ return;
+ }
+ service.startSearchingForSources(filters);
+ }
+
+ @Override
+ public void stopSearchingForSources(AttributionSource source) {
+ BassClientService service = getServiceAndEnforceScan(source);
+ if (service == null) {
+ Log.e(TAG, "Service is null");
+ return;
+ }
+ service.stopSearchingForSources();
+ }
+
+ @Override
+ public boolean isSearchInProgress(AttributionSource source) {
+ BassClientService service = getServiceAndEnforceScan(source);
+ if (service == null) {
+ Log.e(TAG, "Service is null");
+ return false;
+ }
+ return service.isSearchInProgress();
+ }
+
+ @Override
+ public void addSource(
+ BluetoothDevice sink,
+ BluetoothLeBroadcastMetadata sourceMetadata,
+ boolean isGroupOp,
+ AttributionSource source) {
+ BassClientService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ Log.e(TAG, "Service is null");
+ return;
+ }
+ service.addSource(sink, sourceMetadata, isGroupOp);
+ }
+
+ @Override
+ public void modifySource(
+ BluetoothDevice sink,
+ int sourceId,
+ BluetoothLeBroadcastMetadata updatedMetadata,
+ AttributionSource source) {
+ BassClientService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ Log.e(TAG, "Service is null");
+ return;
+ }
+ service.modifySource(sink, sourceId, updatedMetadata);
+ }
+
+ @Override
+ public void removeSource(BluetoothDevice sink, int sourceId, AttributionSource source) {
+ BassClientService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ Log.e(TAG, "Service is null");
+ return;
+ }
+ service.removeSource(sink, sourceId);
+ }
+
+ @Override
+ public List<BluetoothLeBroadcastReceiveState> getAllSources(
+ BluetoothDevice sink, AttributionSource source) {
+ BassClientService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ Log.e(TAG, "Service is null");
+ return Collections.emptyList();
+ }
+ return service.getAllSources(sink);
+ }
+
+ @Override
+ public int getMaximumSourceCapacity(BluetoothDevice sink, AttributionSource source) {
+ BassClientService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ Log.e(TAG, "Service is null");
+ return 0;
+ }
+ return service.getMaximumSourceCapacity(sink);
+ }
+
+ @Override
+ public BluetoothLeBroadcastMetadata getSourceMetadata(
+ BluetoothDevice sink, int sourceId, AttributionSource source) {
+ BassClientService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ Log.e(TAG, "Service is null");
+ return null;
+ }
+ return service.getSourceMetadata(sink, sourceId);
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/bass_client/OWNERS b/android/app/src/com/android/bluetooth/bass_client/OWNERS
deleted file mode 100644
index a7d77894ba..0000000000
--- a/android/app/src/com/android/bluetooth/bass_client/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_leaudio
diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java
index bd483f5925..013c799af7 100644
--- a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java
+++ b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java
@@ -55,7 +55,6 @@ import androidx.annotation.VisibleForTesting;
import com.android.bluetooth.BluetoothStatsLog;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
-import com.android.bluetooth.flags.Flags;
import com.android.modules.utils.build.SdkLevel;
import java.io.FileDescriptor;
@@ -531,10 +530,7 @@ class AdapterProperties {
void cleanupPrevBondRecordsFor(BluetoothDevice device) {
String address = device.getAddress();
- String identityAddress =
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getBrEdrAddress(device, mService)
- : mService.getIdentityAddress(address);
+ String identityAddress = Utils.getBrEdrAddress(device, mService);
int deviceType = mRemoteDevices.getDeviceProperties(device).getDeviceType();
debugLog("cleanupPrevBondRecordsFor: " + device + ", device type: " + deviceType);
if (identityAddress == null) {
@@ -547,10 +543,7 @@ class AdapterProperties {
for (BluetoothDevice existingDevice : mBondedDevices) {
String existingAddress = existingDevice.getAddress();
- String existingIdentityAddress =
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getBrEdrAddress(existingDevice, mService)
- : mService.getIdentityAddress(existingAddress);
+ String existingIdentityAddress = Utils.getBrEdrAddress(existingDevice, mService);
int existingDeviceType =
mRemoteDevices.getDeviceProperties(existingDevice).getDeviceType();
@@ -1100,10 +1093,7 @@ class AdapterProperties {
StringBuilder sb = new StringBuilder();
for (BluetoothDevice device : mBondedDevices) {
String address = device.getAddress();
- String brEdrAddress =
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getBrEdrAddress(device)
- : mService.getIdentityAddress(address);
+ String brEdrAddress = Utils.getBrEdrAddress(device);
if (brEdrAddress.equals(address)) {
writer.println(
" "
diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java
index eff7a6e132..182e75cceb 100644
--- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java
@@ -20,16 +20,12 @@ package com.android.bluetooth.btservice;
import static android.Manifest.permission.BLUETOOTH_CONNECT;
import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
import static android.Manifest.permission.BLUETOOTH_SCAN;
-import static android.Manifest.permission.DUMP;
-import static android.Manifest.permission.LOCAL_MAC_ADDRESS;
-import static android.Manifest.permission.MODIFY_PHONE_STATE;
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE;
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_NONE;
import static android.bluetooth.BluetoothAdapter.nameForState;
import static android.bluetooth.BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
import static android.bluetooth.BluetoothDevice.BOND_NONE;
-import static android.bluetooth.BluetoothDevice.TRANSPORT_AUTO;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
@@ -42,9 +38,6 @@ import static android.bluetooth.IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
-import static com.android.bluetooth.ChangeIds.ENFORCE_CONNECT;
-import static com.android.bluetooth.Utils.callerIsSystem;
-import static com.android.bluetooth.Utils.callerIsSystemOrActiveOrManagedUser;
import static com.android.bluetooth.Utils.getBytesFromAddress;
import static com.android.bluetooth.Utils.isDualModeAudioEnabled;
import static com.android.bluetooth.Utils.isPackageNameAccurate;
@@ -60,7 +53,6 @@ import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.app.Service;
import android.app.admin.DevicePolicyManager;
-import android.app.compat.CompatChanges;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.bluetooth.BluetoothAdapter;
@@ -72,7 +64,6 @@ import android.bluetooth.BluetoothFrameworkInitializer;
import android.bluetooth.BluetoothLeAudio;
import android.bluetooth.BluetoothMap;
import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothProtoEnums;
import android.bluetooth.BluetoothQualityReport;
import android.bluetooth.BluetoothSap;
import android.bluetooth.BluetoothServerSocket;
@@ -82,16 +73,12 @@ import android.bluetooth.BluetoothStatusCodes;
import android.bluetooth.BluetoothUtils;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.BufferConstraints;
-import android.bluetooth.IBluetooth;
-import android.bluetooth.IBluetoothActivityEnergyInfoListener;
import android.bluetooth.IBluetoothCallback;
import android.bluetooth.IBluetoothConnectionCallback;
-import android.bluetooth.IBluetoothHciVendorSpecificCallback;
import android.bluetooth.IBluetoothMetadataListener;
import android.bluetooth.IBluetoothOobDataCallback;
import android.bluetooth.IBluetoothPreferredAudioProfilesCallback;
import android.bluetooth.IBluetoothQualityReportReadyCallback;
-import android.bluetooth.IBluetoothSocketManager;
import android.bluetooth.IncomingRfcommSocketInfo;
import android.bluetooth.OobData;
import android.bluetooth.UidTraffic;
@@ -115,7 +102,6 @@ import android.os.Message;
import android.os.ParcelUuid;
import android.os.Parcelable;
import android.os.PowerManager;
-import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -125,7 +111,6 @@ import android.provider.DeviceConfig;
import android.provider.Settings;
import android.sysprop.BluetoothProperties;
import android.text.TextUtils;
-import android.util.Base64;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
@@ -172,16 +157,10 @@ import com.android.bluetooth.telephony.BluetoothInCallService;
import com.android.bluetooth.vc.VolumeControlService;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.modules.expresslog.Counter;
import com.android.modules.utils.BackgroundThread;
import com.android.modules.utils.BytesMatcher;
-import libcore.util.SneakyThrow;
-
-import com.google.protobuf.InvalidProtocolBufferException;
-
import java.io.FileDescriptor;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.FileVisitResult;
@@ -195,7 +174,6 @@ import java.time.Instant;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -206,14 +184,12 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
-import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Pattern;
-import java.util.stream.Collectors;
public class AdapterService extends Service {
private static final String TAG =
@@ -225,9 +201,6 @@ public class AdapterService extends Service {
private static final int MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT = 4;
private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 100;
- private static final int MIN_ADVT_INSTANCES_FOR_MA = 5;
- private static final int MIN_OFFLOADED_FILTERS = 10;
- private static final int MIN_OFFLOADED_SCAN_STORAGE_BYTES = 1024;
private static final Duration PENDING_SOCKET_HANDOFF_TIMEOUT = Duration.ofMinutes(1);
private static final Duration GENERATE_LOCAL_OOB_DATA_TIMEOUT = Duration.ofSeconds(2);
@@ -309,7 +282,7 @@ public class AdapterService extends Service {
new ArrayList<>();
private BluetoothAdapter mAdapter;
- @VisibleForTesting AdapterProperties mAdapterProperties;
+ private AdapterProperties mAdapterProperties;
private AdapterState mAdapterStateMachine;
private BondStateMachine mBondStateMachine;
private RemoteDevices mRemoteDevices;
@@ -341,10 +314,10 @@ public class AdapterService extends Service {
private BluetoothSocketManagerBinder mBluetoothSocketManagerBinder;
private BluetoothKeystoreService mBluetoothKeystoreService;
- private A2dpService mA2dpService;
- private A2dpSinkService mA2dpSinkService;
private HeadsetService mHeadsetService;
private HeadsetClientService mHeadsetClientService;
+ private A2dpService mA2dpService;
+ private A2dpSinkService mA2dpSinkService;
private BluetoothMapService mMapService;
private MapClientService mMapClientService;
private HidDeviceService mHidDeviceService;
@@ -422,10 +395,6 @@ public class AdapterService extends Service {
return sAdapterService;
}
- AdapterNativeInterface getNative() {
- return mNativeInterface;
- }
-
/** Allow test to set an AdapterService to be return by AdapterService.getAdapterService() */
@VisibleForTesting
public static synchronized void setAdapterService(AdapterService instance) {
@@ -791,10 +760,76 @@ public class AdapterService extends Service {
return mActiveDeviceManager;
}
+ public RemoteDevices getRemoteDevices() {
+ return mRemoteDevices;
+ }
+
public SilenceDeviceManager getSilenceDeviceManager() {
return mSilenceDeviceManager;
}
+ AdapterNativeInterface getNative() {
+ return mNativeInterface;
+ }
+
+ AdapterServiceHandler getHandler() {
+ return mHandler;
+ }
+
+ DatabaseManager getDatabaseManager() {
+ return mDatabaseManager;
+ }
+
+ AdapterProperties getAdapterProperties() {
+ return mAdapterProperties;
+ }
+
+ Map<BluetoothDevice, RemoteCallbackList<IBluetoothMetadataListener>> getMetadataListeners() {
+ return mMetadataListeners;
+ }
+
+ Map<String, CallerInfo> getBondAttemptCallerInfo() {
+ return mBondAttemptCallerInfo;
+ }
+
+ Optional<PhonePolicy> getPhonePolicy() {
+ return mPhonePolicy;
+ }
+
+ BondStateMachine getBondStateMachine() {
+ return mBondStateMachine;
+ }
+
+ CompanionDeviceManager getCompanionDeviceManager() {
+ return mCompanionDeviceManager;
+ }
+
+ BluetoothSocketManagerBinder getBluetoothSocketManagerBinder() {
+ return mBluetoothSocketManagerBinder;
+ }
+
+ RemoteCallbackList<IBluetoothConnectionCallback> getBluetoothConnectionCallbacks() {
+ return mBluetoothConnectionCallbacks;
+ }
+
+ RemoteCallbackList<IBluetoothPreferredAudioProfilesCallback>
+ getPreferredAudioProfilesCallbacks() {
+ return mPreferredAudioProfilesCallbacks;
+ }
+
+ RemoteCallbackList<IBluetoothQualityReportReadyCallback>
+ getBluetoothQualityReportReadyCallbacks() {
+ return mBluetoothQualityReportReadyCallbacks;
+ }
+
+ BluetoothHciVendorSpecificDispatcher getBluetoothHciVendorSpecificDispatcher() {
+ return mBluetoothHciVendorSpecificDispatcher;
+ }
+
+ BluetoothHciVendorSpecificNativeInterface getBluetoothHciVendorSpecificNativeInterface() {
+ return mBluetoothHciVendorSpecificNativeInterface;
+ }
+
/**
* Log L2CAP CoC Server Connection Metrics
*
@@ -1727,14 +1762,6 @@ public class AdapterService extends Service {
* @return false if one of profile is enabled or disabled, true otherwise
*/
boolean isAllProfilesUnknown(BluetoothDevice device) {
- if (mA2dpService != null
- && mA2dpService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
- return false;
- }
- if (mA2dpSinkService != null
- && mA2dpSinkService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
- return false;
- }
if (mHeadsetService != null
&& mHeadsetService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
return false;
@@ -1743,6 +1770,14 @@ public class AdapterService extends Service {
&& mHeadsetClientService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
return false;
}
+ if (mA2dpService != null
+ && mA2dpService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
+ return false;
+ }
+ if (mA2dpSinkService != null
+ && mA2dpSinkService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
+ return false;
+ }
if (mMapClientService != null
&& mMapClientService.getConnectionPolicy(device) != CONNECTION_POLICY_UNKNOWN) {
return false;
@@ -1802,18 +1837,7 @@ public class AdapterService extends Service {
Log.i(TAG, "connectEnabledProfiles: Connecting Coordinated Set Profile");
mCsipSetCoordinatorService.connect(device);
}
- if (mA2dpService != null
- && isProfileSupported(device, BluetoothProfile.A2DP)
- && mA2dpService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) {
- Log.i(TAG, "connectEnabledProfiles: Connecting A2dp");
- mA2dpService.connect(device);
- }
- if (mA2dpSinkService != null
- && isProfileSupported(device, BluetoothProfile.A2DP_SINK)
- && mA2dpSinkService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) {
- Log.i(TAG, "connectEnabledProfiles: Connecting A2dp Sink");
- mA2dpSinkService.connect(device);
- }
+ // Order matters, some devices do not accept A2DP connection before HFP connection
if (mHeadsetService != null
&& isProfileSupported(device, BluetoothProfile.HEADSET)
&& mHeadsetService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) {
@@ -1827,6 +1851,18 @@ public class AdapterService extends Service {
Log.i(TAG, "connectEnabledProfiles: Connecting HFP");
mHeadsetClientService.connect(device);
}
+ if (mA2dpService != null
+ && isProfileSupported(device, BluetoothProfile.A2DP)
+ && mA2dpService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) {
+ Log.i(TAG, "connectEnabledProfiles: Connecting A2dp");
+ mA2dpService.connect(device);
+ }
+ if (mA2dpSinkService != null
+ && isProfileSupported(device, BluetoothProfile.A2DP_SINK)
+ && mA2dpSinkService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) {
+ Log.i(TAG, "connectEnabledProfiles: Connecting A2dp Sink");
+ mA2dpSinkService.connect(device);
+ }
if (mMapClientService != null
&& isProfileSupported(device, BluetoothProfile.MAP_CLIENT)
&& mMapClientService.getConnectionPolicy(device) > CONNECTION_POLICY_FORBIDDEN) {
@@ -1909,10 +1945,10 @@ public class AdapterService extends Service {
/** Initializes all the profile services fields */
private void initProfileServices() {
Log.i(TAG, "initProfileServices: Initializing all bluetooth profile services");
- mA2dpService = A2dpService.getA2dpService();
- mA2dpSinkService = A2dpSinkService.getA2dpSinkService();
mHeadsetService = HeadsetService.getHeadsetService();
mHeadsetClientService = HeadsetClientService.getHeadsetClientService();
+ mA2dpService = A2dpService.getA2dpService();
+ mA2dpSinkService = A2dpSinkService.getA2dpSinkService();
mMapService = BluetoothMapService.getBluetoothMapService();
mMapClientService = MapClientService.getMapClientService();
mHidDeviceService = HidDeviceService.getHidDeviceService();
@@ -1932,7 +1968,7 @@ public class AdapterService extends Service {
@BluetoothAdapter.RfcommListenerResult
@RequiresPermission(BLUETOOTH_CONNECT)
- private int startRfcommListener(
+ int startRfcommListener(
String name, ParcelUuid uuid, PendingIntent pendingIntent, AttributionSource source) {
if (mBluetoothServerSockets.containsKey(uuid.getUuid())) {
Log.d(TAG, "Cannot start RFCOMM listener: UUID " + uuid.getUuid() + "already in use.");
@@ -1949,7 +1985,6 @@ public class AdapterService extends Service {
}
@BluetoothAdapter.RfcommListenerResult
- @VisibleForTesting
int stopRfcommListener(ParcelUuid uuid, AttributionSource source) {
RfcommListenerData listenerData = mBluetoothServerSockets.get(uuid.getUuid());
@@ -1968,7 +2003,6 @@ public class AdapterService extends Service {
return listenerData.closeServerAndPendingSockets(mHandler);
}
- @VisibleForTesting
IncomingRfcommSocketInfo retrievePendingSocketForServiceRecord(
ParcelUuid uuid, AttributionSource source) {
IncomingRfcommSocketInfo socketInfo = new IncomingRfcommSocketInfo();
@@ -2124,7 +2158,6 @@ public class AdapterService extends Service {
}
}
- @VisibleForTesting
boolean isAvailable() {
return !mCleaningUp;
}
@@ -2160,2223 +2193,6 @@ public class AdapterService extends Service {
}
/**
- * There is no leak of this binder since it is never re-used and the process is systematically
- * killed
- */
- @VisibleForTesting
- public static class AdapterServiceBinder extends IBluetooth.Stub {
- private final AdapterService mService;
-
- AdapterServiceBinder(AdapterService svc) {
- mService = svc;
- }
-
- public AdapterService getService() {
- if (!mService.isAvailable()) {
- return null;
- }
- return mService;
- }
-
- @Override
- public int getState() {
- AdapterService service = getService();
- if (service == null) {
- return BluetoothAdapter.STATE_OFF;
- }
-
- return service.getState();
- }
-
- @Override
- public void killBluetoothProcess() {
- mService.enforceCallingPermission(BLUETOOTH_PRIVILEGED, null);
-
- Runnable killAction =
- () -> {
- if (Flags.killInsteadOfExit()) {
- Log.i(TAG, "killBluetoothProcess: Calling killProcess(myPid())");
- Process.killProcess(Process.myPid());
- } else {
- Log.i(TAG, "killBluetoothProcess: Calling System.exit");
- System.exit(0);
- }
- };
-
- // Post on the main handler to let the cleanup complete before calling exit
- mService.mHandler.post(killAction);
-
- try {
- // Wait for Bluetooth to be killed from its main thread
- Thread.sleep(1_000); // SystemServer is waiting 2000 ms, we need to wait less here
- } catch (InterruptedException e) {
- Log.e(TAG, "killBluetoothProcess: Interrupted while waiting for kill");
- }
-
- // Bluetooth cannot be killed on the main thread; it is in a deadLock.
- // Trying to recover by killing the Bluetooth from the binder thread.
- // This is bad :(
- Counter.logIncrement("bluetooth.value_kill_from_binder_thread");
- Log.wtf(TAG, "Failed to kill Bluetooth using its main thread. Trying from binder");
- killAction.run();
- }
-
- @Override
- public void offToBleOn(boolean quietMode, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "offToBleOn")) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- service.offToBleOn(quietMode);
- }
-
- @Override
- public void onToBleOn(AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "onToBleOn")) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- service.onToBleOn();
- }
-
- @Override
- public String getAddress(AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getAddress")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getAddress")) {
- return null;
- }
-
- service.enforceCallingOrSelfPermission(LOCAL_MAC_ADDRESS, null);
-
- return Utils.getAddressStringFromByte(service.mAdapterProperties.getAddress());
- }
-
- @Override
- public List<ParcelUuid> getUuids(AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getUuids")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getUuids")) {
- return Collections.emptyList();
- }
-
- ParcelUuid[] parcels = service.mAdapterProperties.getUuids();
- if (parcels == null) {
- parcels = new ParcelUuid[0];
- }
- return Arrays.asList(parcels);
- }
-
- @Override
- public String getIdentityAddress(String address) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getIdentityAddress")
- || !Utils.checkConnectPermissionForDataDelivery(
- service,
- Utils.getCallingAttributionSource(mService),
- "AdapterService getIdentityAddress")) {
- return null;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getIdentityAddress(address);
- }
-
- @Override
- @NonNull
- public BluetoothAddress getIdentityAddressWithType(@NonNull String address) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(
- service, TAG, "getIdentityAddressWithType")
- || !Utils.checkConnectPermissionForDataDelivery(
- service,
- Utils.getCallingAttributionSource(mService),
- "AdapterService getIdentityAddressWithType")) {
- return new BluetoothAddress(null, BluetoothDevice.ADDRESS_TYPE_UNKNOWN);
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getIdentityAddressWithType(address);
- }
-
- @Override
- public String getName(AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getName")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getName")) {
- return null;
- }
-
- return service.getName();
- }
-
- @Override
- public int getNameLengthForAdvertise(AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(
- service, TAG, "getNameLengthForAdvertise")
- || !Utils.checkAdvertisePermissionForDataDelivery(service, source, TAG)) {
- return -1;
- }
-
- return service.getNameLengthForAdvertise();
- }
-
- @Override
- public boolean setName(String name, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setName")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService setName")) {
- return false;
- }
-
- if (Flags.emptyNamesAreInvalid()) {
- requireNonNull(name);
- name = name.trim();
- if (name.isEmpty()) {
- throw new IllegalArgumentException("Empty names are not valid");
- }
- }
-
- Log.d(TAG, "AdapterServiceBinder.setName(" + name + ")");
- return service.mAdapterProperties.setName(name);
- }
-
- @Override
- public int getScanMode(AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getScanMode")
- || !Utils.checkScanPermissionForDataDelivery(
- service, source, "AdapterService getScanMode")) {
- return SCAN_MODE_NONE;
- }
-
- return service.getScanMode();
- }
-
- @Override
- public int setScanMode(int mode, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setScanMode")
- || !Utils.checkScanPermissionForDataDelivery(
- service, source, "AdapterService setScanMode")) {
- return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- String logCaller = Utils.getUidPidString() + " packageName=" + source.getPackageName();
- CompletableFuture<Boolean> future = new CompletableFuture<>();
- mService.mHandler.post(
- () ->
- future.complete(
- service.getState() == BluetoothAdapter.STATE_ON
- && service.setScanMode(mode, logCaller)));
- return future.join()
- ? BluetoothStatusCodes.SUCCESS
- : BluetoothStatusCodes.ERROR_UNKNOWN;
- }
-
- @Override
- public long getDiscoverableTimeout(AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getDiscoverableTimeout")
- || !Utils.checkScanPermissionForDataDelivery(
- service, source, "AdapterService getDiscoverableTimeout")) {
- return -1;
- }
-
- return service.mAdapterProperties.getDiscoverableTimeout();
- }
-
- @Override
- public int setDiscoverableTimeout(long timeout, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setDiscoverableTimeout")
- || !Utils.checkScanPermissionForDataDelivery(
- service, source, "AdapterService setDiscoverableTimeout")) {
- return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.mAdapterProperties.setDiscoverableTimeout((int) timeout)
- ? BluetoothStatusCodes.SUCCESS
- : BluetoothStatusCodes.ERROR_UNKNOWN;
- }
-
- @Override
- public boolean startDiscovery(AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "startDiscovery")) {
- return false;
- }
-
- if (!Utils.checkScanPermissionForDataDelivery(service, source, "Starting discovery.")) {
- return false;
- }
-
- Log.i(TAG, "startDiscovery: from " + Utils.getUidPidString());
- return service.startDiscovery(source);
- }
-
- @Override
- public boolean cancelDiscovery(AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "cancelDiscovery")
- || !Utils.checkScanPermissionForDataDelivery(
- service, source, "AdapterService cancelDiscovery")) {
- return false;
- }
-
- Log.i(TAG, "cancelDiscovery: from " + Utils.getUidPidString());
- return service.mNativeInterface.cancelDiscovery();
- }
-
- @Override
- public boolean isDiscovering(AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "isDiscovering")
- || !Utils.checkScanPermissionForDataDelivery(
- service, source, "AdapterService isDiscovering")) {
- return false;
- }
-
- return service.mAdapterProperties.isDiscovering();
- }
-
- @Override
- public long getDiscoveryEndMillis(AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getDiscoveryEndMillis")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return -1;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.mAdapterProperties.discoveryEndMillis();
- }
-
- @Override
- public List<BluetoothDevice> getMostRecentlyConnectedDevices(AttributionSource source) {
- // don't check caller, may be called from system UI
- AdapterService service = getService();
- if (service == null
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getMostRecentlyConnectedDevices")) {
- return Collections.emptyList();
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.mDatabaseManager.getMostRecentlyConnectedDevices();
- }
-
- @Override
- public List<BluetoothDevice> getBondedDevices(AttributionSource source) {
- // don't check caller, may be called from system UI
- AdapterService service = getService();
- if (service == null
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getBondedDevices")) {
- return Collections.emptyList();
- }
-
- return Arrays.asList(service.getBondedDevices());
- }
-
- @Override
- public int getAdapterConnectionState() {
- // don't check caller, may be called from system UI
- AdapterService service = getService();
- if (service == null) {
- return BluetoothAdapter.STATE_DISCONNECTED;
- }
-
- return service.mAdapterProperties.getConnectionState();
- }
-
- /**
- * This method has an associated binder cache. The invalidation methods must be changed if
- * the logic behind this method changes.
- */
- @Override
- public int getProfileConnectionState(int profile, AttributionSource source) {
- AdapterService service = getService();
- boolean checkConnect = false;
- final int callingUid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- try {
- checkConnect = CompatChanges.isChangeEnabled(ENFORCE_CONNECT, callingUid);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(
- service, TAG, "getProfileConnectionState")
- || (checkConnect
- && !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getProfileConnectionState"))) {
- return STATE_DISCONNECTED;
- }
-
- return service.mAdapterProperties.getProfileConnectionState(profile);
- }
-
- @Override
- public boolean createBond(
- BluetoothDevice device,
- int transport,
- AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "createBond")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService createBond")) {
- return false;
- }
-
- Log.i(
- TAG,
- "createBond:"
- + (" device=" + device)
- + (" transport=" + transport)
- + (" from " + Utils.getUidPidString()));
- return service.createBond(
- device, transport, null, null, source.getPackageName());
- }
-
- @Override
- public boolean createBondOutOfBand(
- BluetoothDevice device,
- int transport,
- OobData remoteP192Data,
- OobData remoteP256Data,
- AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "createBond")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService createBond")) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- Log.i(
- TAG,
- "createBondOutOfBand:"
- + (" device=" + device)
- + (" transport=" + transport)
- + (" from " + Utils.getUidPidString()));
- return service.createBond(
- device, transport, remoteP192Data, remoteP256Data, source.getPackageName());
- }
-
- @Override
- public boolean cancelBondProcess(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "cancelBondProcess")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService cancelBondProcess")) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- Log.i(TAG, "cancelBondProcess: device=" + device + ", from " + Utils.getUidPidString());
-
- DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
- if (deviceProp != null) {
- deviceProp.setBondingInitiatedLocally(false);
- }
-
- service.logUserBondResponse(device, false, source);
- return service.mNativeInterface.cancelBond(getBytesFromAddress(device.getAddress()));
- }
-
- @Override
- public boolean removeBond(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "removeBond")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService removeBond")) {
- return false;
- }
-
- Log.i(TAG, "removeBond: device=" + device + ", from " + Utils.getUidPidString());
-
- DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
- if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) {
- Log.w(
- TAG,
- device
- + " cannot be removed since "
- + ((deviceProp == null)
- ? "properties are empty"
- : "bond state is " + deviceProp.getBondState()));
- return false;
- }
- service.logUserBondResponse(device, false, source);
- service.mBondAttemptCallerInfo.remove(device.getAddress());
- service.mPhonePolicy.ifPresent(policy -> policy.onRemoveBondRequest(device));
- deviceProp.setBondingInitiatedLocally(false);
-
- Message msg = service.mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND);
- msg.obj = device;
- service.mBondStateMachine.sendMessage(msg);
- return true;
- }
-
- @Override
- public int getBondState(BluetoothDevice device, AttributionSource source) {
- // don't check caller, may be called from system UI
- AdapterService service = getService();
- if (service == null
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getBondState")) {
- return BluetoothDevice.BOND_NONE;
- }
-
- return service.getBondState(device);
- }
-
- @Override
- public boolean isBondingInitiatedLocally(BluetoothDevice device, AttributionSource source) {
- // don't check caller, may be called from system UI
- AdapterService service = getService();
- if (service == null
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService isBondingInitiatedLocally")) {
- return false;
- }
-
- DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
- return deviceProp != null && deviceProp.isBondingInitiatedLocally();
- }
-
- @Override
- public void generateLocalOobData(
- int transport, IBluetoothOobDataCallback callback, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "generateLocalOobData")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.generateLocalOobData(transport, callback);
- }
-
- @Override
- public long getSupportedProfiles(AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return 0;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return Config.getSupportedProfilesBitMask();
- }
-
- @Override
- public int getConnectionState(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getConnectionState")) {
- return BluetoothDevice.CONNECTION_STATE_DISCONNECTED;
- }
-
- return service.getConnectionState(device);
- }
-
- @Override
- public int getConnectionHandle(
- BluetoothDevice device, int transport, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getConnectionHandle")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return BluetoothDevice.ERROR;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getConnectionHandle(device, transport);
- }
-
- @Override
- public boolean canBondWithoutDialog(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.canBondWithoutDialog(device);
- }
-
- @Override
- public String getPackageNameOfBondingApplication(
- BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
-
- if (service == null
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getPackageNameOfBondingApplication(device);
- }
-
- @Override
- public boolean removeActiveDevice(@ActiveDeviceUse int profiles, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "removeActiveDevice")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- Log.i(
- TAG,
- "removeActiveDevice: profiles="
- + profiles
- + ", from "
- + Utils.getUidPidString());
- return service.setActiveDevice(null, profiles);
- }
-
- @Override
- public boolean setActiveDevice(
- BluetoothDevice device, @ActiveDeviceUse int profiles, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setActiveDevice")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- Log.i(
- TAG,
- "setActiveDevice: device="
- + device
- + ", profiles="
- + profiles
- + ", from "
- + Utils.getUidPidString());
-
- return service.setActiveDevice(device, profiles);
- }
-
- @Override
- public List<BluetoothDevice> getActiveDevices(
- @ActiveDeviceProfile int profile, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getActiveDevices")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return Collections.emptyList();
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getActiveDevices(profile);
- }
-
- @Override
- public int connectAllEnabledProfiles(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null || !service.isEnabled()) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "connectAllEnabledProfiles")) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
- }
- if (device == null) {
- throw new IllegalArgumentException("device cannot be null");
- }
- if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
- throw new IllegalArgumentException("device cannot have an invalid address");
- }
- if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
- }
-
- service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- Log.i(
- TAG,
- "connectAllEnabledProfiles: device="
- + device
- + ", from "
- + Utils.getUidPidString());
- MetricsLogger.getInstance()
- .logBluetoothEvent(
- device,
- BluetoothStatsLog
- .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__INITIATOR_CONNECTION,
- BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__START,
- source.getUid());
-
- try {
- return service.connectAllEnabledProfiles(device);
- } catch (Exception e) {
- Log.v(TAG, "connectAllEnabledProfiles() failed", e);
- SneakyThrow.sneakyThrow(e);
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public int disconnectAllEnabledProfiles(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- if (!callerIsSystemOrActiveOrManagedUser(
- service, TAG, "disconnectAllEnabledProfiles")) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
- }
- if (device == null) {
- throw new IllegalArgumentException("device cannot be null");
- }
- if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
- throw new IllegalArgumentException("device cannot have an invalid address");
- }
- if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- Log.i(
- TAG,
- "disconnectAllEnabledProfiles: device="
- + device
- + ", from "
- + Utils.getUidPidString());
-
- try {
- return service.disconnectAllEnabledProfiles(device);
- } catch (Exception e) {
- Log.v(TAG, "disconnectAllEnabledProfiles() failed", e);
- SneakyThrow.sneakyThrow(e);
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public String getRemoteName(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteName")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getRemoteName")) {
- return null;
- }
-
- return service.getRemoteName(device);
- }
-
- @Override
- public int getRemoteType(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteType")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getRemoteType")) {
- return BluetoothDevice.DEVICE_TYPE_UNKNOWN;
- }
-
- return service.getRemoteType(device);
- }
-
- @Override
- public String getRemoteAlias(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteAlias")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getRemoteAlias")) {
- return null;
- }
-
- DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
- return deviceProp != null ? deviceProp.getAlias() : null;
- }
-
- @Override
- public int setRemoteAlias(BluetoothDevice device, String name, AttributionSource source) {
- AdapterService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setRemoteAlias")) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
- }
- if (name != null && name.isEmpty()) {
- throw new IllegalArgumentException("alias cannot be the empty string");
- }
-
- if (!Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService setRemoteAlias")) {
- return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
- }
-
- Utils.enforceCdmAssociationIfNotBluetoothPrivileged(
- service, service.mCompanionDeviceManager, source, device);
-
- DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
- if (deviceProp == null) {
- return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED;
- }
- deviceProp.setAlias(device, name);
- return BluetoothStatusCodes.SUCCESS;
- }
-
- @Override
- public int getRemoteClass(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteClass")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getRemoteClass")) {
- return 0;
- }
-
- return service.getRemoteClass(device);
- }
-
- @Override
- public List<ParcelUuid> getRemoteUuids(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteUuids")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getRemoteUuids")) {
- return Collections.emptyList();
- }
-
- final ParcelUuid[] parcels = service.getRemoteUuids(device);
- if (parcels == null) {
- return null;
- }
- return Arrays.asList(parcels);
- }
-
- @Override
- public boolean fetchRemoteUuids(
- BluetoothDevice device, int transport, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "fetchRemoteUuids")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService fetchRemoteUuids")) {
- return false;
- }
- if (transport != TRANSPORT_AUTO) {
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- }
-
- Log.i(
- TAG,
- "fetchRemoteUuids: device="
- + device
- + ", transport="
- + transport
- + ", from "
- + Utils.getUidPidString());
-
- service.mRemoteDevices.fetchUuids(device, transport);
- MetricsLogger.getInstance().cacheCount(BluetoothProtoEnums.SDP_FETCH_UUID_REQUEST, 1);
- return true;
- }
-
- @Override
- public boolean setPin(
- BluetoothDevice device,
- boolean accept,
- int len,
- byte[] pinCode,
- AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPin")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService setPin")) {
- return false;
- }
-
- DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
- // Only allow setting a pin in bonding state, or bonded state in case of security
- // upgrade.
- if (deviceProp == null || !deviceProp.isBondingOrBonded()) {
- Log.e(TAG, "setPin: device=" + device + ", not bonding");
- return false;
- }
- if (pinCode.length != len) {
- android.util.EventLog.writeEvent(
- 0x534e4554, "139287605", -1, "PIN code length mismatch");
- return false;
- }
- service.logUserBondResponse(device, accept, source);
- Log.i(
- TAG,
- "setPin: device="
- + device
- + ", accept="
- + accept
- + ", from "
- + Utils.getUidPidString());
- return service.mNativeInterface.pinReply(
- getBytesFromAddress(device.getAddress()), accept, len, pinCode);
- }
-
- @Override
- public boolean setPasskey(
- BluetoothDevice device,
- boolean accept,
- int len,
- byte[] passkey,
- AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPasskey")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService setPasskey")) {
- return false;
- }
-
- DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
- if (deviceProp == null || !deviceProp.isBonding()) {
- Log.e(TAG, "setPasskey: device=" + device + ", not bonding");
- return false;
- }
- if (passkey.length != len) {
- android.util.EventLog.writeEvent(
- 0x534e4554, "139287605", -1, "Passkey length mismatch");
- return false;
- }
- service.logUserBondResponse(device, accept, source);
- Log.i(
- TAG,
- "setPasskey: device="
- + device
- + ", accept="
- + accept
- + ", from "
- + Utils.getUidPidString());
-
- return service.mNativeInterface.sspReply(
- getBytesFromAddress(device.getAddress()),
- AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY,
- accept,
- Utils.byteArrayToInt(passkey));
- }
-
- @Override
- public boolean setPairingConfirmation(
- BluetoothDevice device, boolean accept, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPairingConfirmation")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
- if (deviceProp == null || !deviceProp.isBonding()) {
- Log.e(TAG, "setPairingConfirmation: device=" + device + ", not bonding");
- return false;
- }
- service.logUserBondResponse(device, accept, source);
- Log.i(
- TAG,
- "setPairingConfirmation: device="
- + device
- + ", accept="
- + accept
- + ", from "
- + Utils.getUidPidString());
-
- return service.mNativeInterface.sspReply(
- getBytesFromAddress(device.getAddress()),
- AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION,
- accept,
- 0);
- }
-
- @Override
- public boolean getSilenceMode(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getSilenceMode")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.mSilenceDeviceManager.getSilenceMode(device);
- }
-
- @Override
- public boolean setSilenceMode(
- BluetoothDevice device, boolean silence, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setSilenceMode")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- service.mSilenceDeviceManager.setSilenceMode(device, silence);
- return true;
- }
-
- @Override
- public int getPhonebookAccessPermission(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(
- service, TAG, "getPhonebookAccessPermission")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getPhonebookAccessPermission")) {
- return BluetoothDevice.ACCESS_UNKNOWN;
- }
-
- return service.getPhonebookAccessPermission(device);
- }
-
- @Override
- public boolean setPhonebookAccessPermission(
- BluetoothDevice device, int value, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(
- service, TAG, "setPhonebookAccessPermission")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- service.setPhonebookAccessPermission(device, value);
- return true;
- }
-
- @Override
- public int getMessageAccessPermission(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(
- service, TAG, "getMessageAccessPermission")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getMessageAccessPermission")) {
- return BluetoothDevice.ACCESS_UNKNOWN;
- }
-
- return service.getMessageAccessPermission(device);
- }
-
- @Override
- public boolean setMessageAccessPermission(
- BluetoothDevice device, int value, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(
- service, TAG, "setMessageAccessPermission")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- service.setMessageAccessPermission(device, value);
- return true;
- }
-
- @Override
- public int getSimAccessPermission(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getSimAccessPermission")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getSimAccessPermission")) {
- return BluetoothDevice.ACCESS_UNKNOWN;
- }
-
- return service.getSimAccessPermission(device);
- }
-
- @Override
- public boolean setSimAccessPermission(
- BluetoothDevice device, int value, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setSimAccessPermission")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- service.setSimAccessPermission(device, value);
- return true;
- }
-
- @Override
- public void logL2capcocServerConnection(
- BluetoothDevice device,
- int port,
- boolean isSecured,
- int result,
- long socketCreationTimeMillis,
- long socketCreationLatencyMillis,
- long socketConnectionTimeMillis,
- long timeoutMillis) {
- AdapterService service = getService();
- if (service == null) {
- return;
- }
- service.logL2capcocServerConnection(
- device,
- port,
- isSecured,
- result,
- socketCreationTimeMillis,
- socketCreationLatencyMillis,
- socketConnectionTimeMillis,
- timeoutMillis,
- Binder.getCallingUid());
- }
-
- @Override
- public IBluetoothSocketManager getSocketManager() {
- AdapterService service = getService();
- if (service == null) {
- return null;
- }
-
- return IBluetoothSocketManager.Stub.asInterface(service.mBluetoothSocketManagerBinder);
- }
-
- @Override
- public void logL2capcocClientConnection(
- BluetoothDevice device,
- int port,
- boolean isSecured,
- int result,
- long socketCreationTimeNanos,
- long socketCreationLatencyNanos,
- long socketConnectionTimeNanos) {
- AdapterService service = getService();
- if (service == null) {
- return;
- }
- service.logL2capcocClientConnection(
- device,
- port,
- isSecured,
- result,
- socketCreationTimeNanos,
- socketCreationLatencyNanos,
- socketConnectionTimeNanos,
- Binder.getCallingUid());
- }
-
- @Override
- public void logRfcommConnectionAttempt(
- BluetoothDevice device,
- boolean isSecured,
- int resultCode,
- long socketCreationTimeNanos,
- boolean isSerialPort) {
- AdapterService service = getService();
- if (service == null) {
- return;
- }
- service.logRfcommConnectionAttempt(
- device,
- isSecured,
- resultCode,
- socketCreationTimeNanos,
- isSerialPort,
- Binder.getCallingUid());
- }
-
- @Override
- public boolean sdpSearch(
- BluetoothDevice device, ParcelUuid uuid, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "sdpSearch")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService sdpSearch")) {
- return false;
- }
- return service.sdpSearch(device, uuid);
- }
-
- @Override
- public int getBatteryLevel(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getBatteryLevel")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getBatteryLevel")) {
- return BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
- }
-
- DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
- if (deviceProp == null) {
- return BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
- }
- return deviceProp.getBatteryLevel();
- }
-
- @Override
- public int getMaxConnectedAudioDevices(AttributionSource source) {
- // don't check caller, may be called from system UI
- AdapterService service = getService();
- if (service == null
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getMaxConnectedAudioDevices")) {
- return -1;
- }
-
- return service.getMaxConnectedAudioDevices();
- }
-
- @Override
- public boolean factoryReset(AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.factoryReset();
- }
-
- @Override
- public void registerBluetoothConnectionCallback(
- IBluetoothConnectionCallback callback, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(
- service, TAG, "registerBluetoothConnectionCallback")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.mBluetoothConnectionCallbacks.register(callback);
- }
-
- @Override
- public void unregisterBluetoothConnectionCallback(
- IBluetoothConnectionCallback callback, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(
- service, TAG, "unregisterBluetoothConnectionCallback")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.mBluetoothConnectionCallbacks.unregister(callback);
- }
-
- @Override
- public void registerCallback(IBluetoothCallback callback, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "registerCallback")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- service.registerRemoteCallback(callback);
- }
-
- @Override
- public void unregisterCallback(IBluetoothCallback callback, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "unregisterCallback")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- service.unregisterRemoteCallback(callback);
- }
-
- @Override
- public boolean isMultiAdvertisementSupported() {
- AdapterService service = getService();
- if (service == null) {
- return false;
- }
-
- int val = service.mAdapterProperties.getNumOfAdvertisementInstancesSupported();
- return val >= MIN_ADVT_INSTANCES_FOR_MA;
- }
-
- /**
- * This method has an associated binder cache. The invalidation methods must be changed if
- * the logic behind this method changes.
- */
- @Override
- public boolean isOffloadedFilteringSupported() {
- AdapterService service = getService();
- if (service == null) {
- return false;
- }
-
- int val = service.getNumOfOffloadedScanFilterSupported();
- return val >= MIN_OFFLOADED_FILTERS;
- }
-
- @Override
- public boolean isOffloadedScanBatchingSupported() {
- AdapterService service = getService();
- if (service == null) {
- return false;
- }
-
- int val = service.getOffloadedScanResultStorage();
- return val >= MIN_OFFLOADED_SCAN_STORAGE_BYTES;
- }
-
- @Override
- public boolean isLe2MPhySupported() {
- AdapterService service = getService();
- if (service == null) {
- return false;
- }
-
- return service.isLe2MPhySupported();
- }
-
- @Override
- public boolean isLeCodedPhySupported() {
- AdapterService service = getService();
- if (service == null) {
- return false;
- }
-
- return service.isLeCodedPhySupported();
- }
-
- @Override
- public boolean isLeExtendedAdvertisingSupported() {
- AdapterService service = getService();
- if (service == null) {
- return false;
- }
-
- return service.isLeExtendedAdvertisingSupported();
- }
-
- @Override
- public boolean isLePeriodicAdvertisingSupported() {
- AdapterService service = getService();
- if (service == null) {
- return false;
- }
-
- return service.isLePeriodicAdvertisingSupported();
- }
-
- @Override
- public int isLeAudioSupported() {
- AdapterService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
-
- Set<Integer> supportedProfileServices =
- Arrays.stream(Config.getSupportedProfiles())
- .boxed()
- .collect(Collectors.toSet());
- int[] leAudioUnicastProfiles = Config.getLeAudioUnicastProfiles();
-
- if (Arrays.stream(leAudioUnicastProfiles)
- .allMatch(supportedProfileServices::contains)) {
- return BluetoothStatusCodes.FEATURE_SUPPORTED;
- }
-
- return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
- }
-
- @Override
- public int isLeAudioBroadcastSourceSupported() {
- AdapterService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
-
- long supportBitMask = Config.getSupportedProfilesBitMask();
- if ((supportBitMask & (1 << BluetoothProfile.LE_AUDIO_BROADCAST)) != 0) {
- return BluetoothStatusCodes.FEATURE_SUPPORTED;
- }
-
- return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
- }
-
- @Override
- public int isLeAudioBroadcastAssistantSupported() {
- AdapterService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
-
- int[] supportedProfileServices = Config.getSupportedProfiles();
-
- if (Arrays.stream(supportedProfileServices)
- .anyMatch(
- profileId ->
- profileId == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)) {
- return BluetoothStatusCodes.FEATURE_SUPPORTED;
- }
-
- return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
- }
-
- @Override
- public int isDistanceMeasurementSupported(AttributionSource source) {
- AdapterService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- } else if (!callerIsSystemOrActiveOrManagedUser(
- service, TAG, "isDistanceMeasurementSupported")) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
- } else if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return BluetoothStatusCodes.FEATURE_SUPPORTED;
- }
-
- @Override
- public int getLeMaximumAdvertisingDataLength() {
- AdapterService service = getService();
- if (service == null) {
- return 0;
- }
-
- return service.getLeMaximumAdvertisingDataLength();
- }
-
- @Override
- public boolean isActivityAndEnergyReportingSupported() {
- AdapterService service = getService();
- if (service == null) {
- return false;
- }
-
- return service.mAdapterProperties.isActivityAndEnergyReportingSupported();
- }
-
- @Override
- public BluetoothActivityEnergyInfo reportActivityInfo(AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.reportActivityInfo();
- }
-
- @Override
- public boolean registerMetadataListener(
- IBluetoothMetadataListener listener,
- BluetoothDevice device,
- AttributionSource source) {
- requireNonNull(device);
- requireNonNull(listener);
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(
- service, TAG, "registerMetadataListener")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- service.mHandler.post(
- () ->
- service.mMetadataListeners
- .computeIfAbsent(device, k -> new RemoteCallbackList())
- .register(listener));
-
- return true;
- }
-
- @Override
- public boolean unregisterMetadataListener(
- IBluetoothMetadataListener listener,
- BluetoothDevice device,
- AttributionSource source) {
- requireNonNull(device);
- requireNonNull(listener);
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(
- service, TAG, "unregisterMetadataListener")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- service.mHandler.post(
- () ->
- service.mMetadataListeners.computeIfPresent(
- device,
- (k, v) -> {
- v.unregister(listener);
- if (v.getRegisteredCallbackCount() == 0) {
- return null;
- }
- return v;
- }));
- return true;
- }
-
- @Override
- public boolean setMetadata(
- BluetoothDevice device, int key, byte[] value, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setMetadata")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.setMetadata(device, key, value);
- }
-
- @Override
- public byte[] getMetadata(BluetoothDevice device, int key, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getMetadata")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getMetadata(device, key);
- }
-
- @Override
- public int isRequestAudioPolicyAsSinkSupported(
- BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(
- service, TAG, "isRequestAudioPolicyAsSinkSupported")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return BluetoothStatusCodes.FEATURE_NOT_CONFIGURED;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.isRequestAudioPolicyAsSinkSupported(device);
- }
-
- @Override
- public int requestAudioPolicyAsSink(
- BluetoothDevice device,
- BluetoothSinkAudioPolicy policies,
- AttributionSource source) {
- AdapterService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- } else if (!callerIsSystemOrActiveOrManagedUser(
- service, TAG, "requestAudioPolicyAsSink")) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
- } else if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.requestAudioPolicyAsSink(device, policies);
- }
-
- @Override
- public BluetoothSinkAudioPolicy getRequestedAudioPolicyAsSink(
- BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(
- service, TAG, "getRequestedAudioPolicyAsSink")
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getRequestedAudioPolicyAsSink(device);
- }
-
- @Override
- public void requestActivityInfo(
- IBluetoothActivityEnergyInfoListener listener, AttributionSource source) {
- BluetoothActivityEnergyInfo info = reportActivityInfo(source);
- try {
- listener.onBluetoothActivityEnergyInfoAvailable(info);
- } catch (RemoteException e) {
- Log.e(TAG, "onBluetoothActivityEnergyInfo: RemoteException", e);
- }
- }
-
- @Override
- public void bleOnToOn(AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "bleOnToOn")) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- service.bleOnToOn();
- }
-
- @Override
- public void bleOnToOff(AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "bleOnToOff")) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- service.bleOnToOff();
- }
-
- @Override
- public void dump(FileDescriptor fd, String[] args) {
- PrintWriter writer = new PrintWriter(new FileOutputStream(fd));
- AdapterService service = getService();
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(DUMP, null);
-
- service.dump(fd, writer, args);
- writer.close();
- }
-
- @Override
- public boolean allowLowLatencyAudio(boolean allowed, BluetoothDevice device) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "allowLowLatencyAudio")
- || !Utils.checkConnectPermissionForDataDelivery(
- service,
- Utils.getCallingAttributionSource(service),
- "AdapterService allowLowLatencyAudio")) {
- return false;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.allowLowLatencyAudio(allowed, device);
- }
-
- @Override
- public int startRfcommListener(
- String name,
- ParcelUuid uuid,
- PendingIntent pendingIntent,
- AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "startRfcommListener")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService startRfcommListener")) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.startRfcommListener(name, uuid, pendingIntent, source);
- }
-
- @Override
- public int stopRfcommListener(ParcelUuid uuid, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(service, TAG, "stopRfcommListener")
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService stopRfcommListener")) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.stopRfcommListener(uuid, source);
- }
-
- @Override
- public IncomingRfcommSocketInfo retrievePendingSocketForServiceRecord(
- ParcelUuid uuid, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(
- service, TAG, "retrievePendingSocketForServiceRecord")
- || !Utils.checkConnectPermissionForDataDelivery(
- service,
- source,
- "AdapterService retrievePendingSocketForServiceRecord")) {
- return null;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.retrievePendingSocketForServiceRecord(uuid, source);
- }
-
- @Override
- public void setForegroundUserId(int userId, AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !Utils.checkConnectPermissionForDataDelivery(
- service,
- Utils.getCallingAttributionSource(mService),
- "AdapterService setForegroundUserId")) {
- return;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- Utils.setForegroundUserId(userId);
- }
-
- @Override
- public int setPreferredAudioProfiles(
- BluetoothDevice device, Bundle modeToProfileBundle, AttributionSource source) {
- AdapterService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setPreferredAudioProfiles")) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
- }
- requireNonNull(device);
- requireNonNull(modeToProfileBundle);
- if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
- throw new IllegalArgumentException("device cannot have an invalid address");
- }
- if (service.getBondState(device) != BluetoothDevice.BOND_BONDED) {
- return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED;
- }
- if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.setPreferredAudioProfiles(device, modeToProfileBundle);
- }
-
- @Override
- public Bundle getPreferredAudioProfiles(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null) {
- return Bundle.EMPTY;
- }
- if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "getPreferredAudioProfiles")) {
- return Bundle.EMPTY;
- }
- requireNonNull(device);
- if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
- throw new IllegalArgumentException("device cannot have an invalid address");
- }
- if (service.getBondState(device) != BluetoothDevice.BOND_BONDED) {
- return Bundle.EMPTY;
- }
- if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return Bundle.EMPTY;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getPreferredAudioProfiles(device);
- }
-
- @Override
- public int notifyActiveDeviceChangeApplied(
- BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- if (!callerIsSystem(TAG, "notifyActiveDeviceChangeApplied")) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
- }
- requireNonNull(device);
- if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
- throw new IllegalArgumentException("device cannot have an invalid address");
- }
- if (service.getBondState(device) != BluetoothDevice.BOND_BONDED) {
- return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED;
- }
- if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.notifyActiveDeviceChangeApplied(device);
- }
-
- @Override
- public int isDualModeAudioEnabled(AttributionSource source) {
- AdapterService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- if (!Utils.isDualModeAudioEnabled()) {
- return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
- }
-
- return BluetoothStatusCodes.SUCCESS;
- }
-
- @Override
- public int registerPreferredAudioProfilesChangedCallback(
- IBluetoothPreferredAudioProfilesCallback callback, AttributionSource source) {
- AdapterService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- if (!callerIsSystemOrActiveOrManagedUser(
- service, TAG, "registerPreferredAudioProfilesChangedCallback")) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
- }
- requireNonNull(callback);
- if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- // If LE only mode is enabled, the dual mode audio feature is disabled
- if (!Utils.isDualModeAudioEnabled()) {
- return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
- }
-
- service.mPreferredAudioProfilesCallbacks.register(callback);
- return BluetoothStatusCodes.SUCCESS;
- }
-
- @Override
- public int unregisterPreferredAudioProfilesChangedCallback(
- IBluetoothPreferredAudioProfilesCallback callback, AttributionSource source) {
- AdapterService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- if (!callerIsSystemOrActiveOrManagedUser(
- service, TAG, "unregisterPreferredAudioProfilesChangedCallback")) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
- }
- requireNonNull(callback);
- if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- if (!service.mPreferredAudioProfilesCallbacks.unregister(callback)) {
- Log.e(
- TAG,
- "unregisterPreferredAudioProfilesChangedCallback: callback was never "
- + "registered");
- return BluetoothStatusCodes.ERROR_CALLBACK_NOT_REGISTERED;
- }
- return BluetoothStatusCodes.SUCCESS;
- }
-
- @Override
- public int registerBluetoothQualityReportReadyCallback(
- IBluetoothQualityReportReadyCallback callback, AttributionSource source) {
- AdapterService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- if (!callerIsSystemOrActiveOrManagedUser(
- service, TAG, "registerBluetoothQualityReportReadyCallback")) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
- }
- requireNonNull(callback);
- if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- service.mBluetoothQualityReportReadyCallbacks.register(callback);
- return BluetoothStatusCodes.SUCCESS;
- }
-
- @Override
- public int unregisterBluetoothQualityReportReadyCallback(
- IBluetoothQualityReportReadyCallback callback, AttributionSource source) {
- AdapterService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- if (!callerIsSystemOrActiveOrManagedUser(
- service, TAG, "unregisterBluetoothQualityReportReadyCallback")) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
- }
- requireNonNull(callback);
- if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- if (!service.mBluetoothQualityReportReadyCallbacks.unregister(callback)) {
- Log.e(
- TAG,
- "unregisterBluetoothQualityReportReadyCallback: callback was never "
- + "registered");
- return BluetoothStatusCodes.ERROR_CALLBACK_NOT_REGISTERED;
- }
- return BluetoothStatusCodes.SUCCESS;
- }
-
- @Override
- public void registerHciVendorSpecificCallback(
- IBluetoothHciVendorSpecificCallback callback, int[] eventCodes) {
- AdapterService service = getService();
- if (service == null) {
- return;
- }
- if (!callerIsSystemOrActiveOrManagedUser(
- service, TAG, "registerHciVendorSpecificCallback")) {
- throw new SecurityException("not allowed");
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- requireNonNull(callback);
- requireNonNull(eventCodes);
-
- Set<Integer> eventCodesSet =
- Arrays.stream(eventCodes).boxed().collect(Collectors.toSet());
- if (eventCodesSet.stream()
- .anyMatch((n) -> (n < 0) || (n >= 0x52 && n < 0x60) || (n > 0xff))) {
- throw new IllegalArgumentException("invalid vendor-specific event code");
- }
-
- service.mBluetoothHciVendorSpecificDispatcher.register(callback, eventCodesSet);
- }
-
- @Override
- public void unregisterHciVendorSpecificCallback(
- IBluetoothHciVendorSpecificCallback callback) {
- AdapterService service = getService();
- if (service == null) {
- return;
- }
- if (!callerIsSystemOrActiveOrManagedUser(
- service, TAG, "unregisterHciVendorSpecificCallback")) {
- throw new SecurityException("not allowed");
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- requireNonNull(callback);
-
- service.mBluetoothHciVendorSpecificDispatcher.unregister(callback);
- }
-
- @Override
- public void sendHciVendorSpecificCommand(
- int ocf, byte[] parameters, IBluetoothHciVendorSpecificCallback callback) {
- AdapterService service = getService();
- if (service == null) {
- return;
- }
- if (!callerIsSystemOrActiveOrManagedUser(
- service, TAG, "sendHciVendorSpecificCommand")) {
- throw new SecurityException("not allowed");
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- // Open this no-op android command for test purpose
- int getVendorCapabilitiesOcf = 0x153;
- if (ocf < 0
- || (ocf >= 0x150 && ocf < 0x160 && ocf != getVendorCapabilitiesOcf)
- || (ocf > 0x3ff)) {
- throw new IllegalArgumentException("invalid vendor-specific event code");
- }
- requireNonNull(parameters);
- if (parameters.length > 255) {
- throw new IllegalArgumentException("Parameters size is too big");
- }
-
- Optional<byte[]> cookie =
- service.mBluetoothHciVendorSpecificDispatcher.getRegisteredCookie(callback);
- if (!cookie.isPresent()) {
- Log.e(TAG, "send command without registered callback");
- throw new IllegalStateException("callback not registered");
- }
-
- service.mBluetoothHciVendorSpecificNativeInterface.sendCommand(
- ocf, parameters, cookie.get());
- }
-
- @Override
- public int getOffloadedTransportDiscoveryDataScanSupported(AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !callerIsSystemOrActiveOrManagedUser(
- service, TAG, "getOffloadedTransportDiscoveryDataScanSupported")
- || !Utils.checkScanPermissionForDataDelivery(
- service, source, "getOffloadedTransportDiscoveryDataScanSupported")) {
- return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getOffloadedTransportDiscoveryDataScanSupported();
- }
-
- @Override
- public boolean isMediaProfileConnected(AttributionSource source) {
- AdapterService service = getService();
- if (service == null
- || !Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService.isMediaProfileConnected")) {
- return false;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.isMediaProfileConnected();
- }
-
- @Override
- public IBinder getBluetoothGatt() {
- AdapterService service = getService();
- return service == null ? null : service.getBluetoothGatt();
- }
-
- @Override
- public IBinder getBluetoothScan() {
- AdapterService service = getService();
- return service == null ? null : service.getBluetoothScan();
- }
-
- @Override
- public void unregAllGattClient(AttributionSource source) {
- AdapterService service = getService();
- if (service == null) {
- return;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.unregAllGattClient(source);
- }
-
- @Override
- public IBinder getProfile(int profileId) {
- AdapterService service = getService();
- if (service == null) {
- return null;
- }
-
- return service.getProfile(profileId);
- }
-
- @Override
- public int setActiveAudioDevicePolicy(
- BluetoothDevice device, int activeAudioDevicePolicy, AttributionSource source) {
- AdapterService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setActiveAudioDevicePolicy")) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
- }
- if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
- throw new IllegalArgumentException("device cannot have an invalid address");
- }
- if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.mDatabaseManager.setActiveAudioDevicePolicy(
- device, activeAudioDevicePolicy);
- }
-
- @Override
- public int getActiveAudioDevicePolicy(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null) {
- return BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT;
- }
- if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "getActiveAudioDevicePolicy")) {
- throw new IllegalStateException(
- "Caller is not the system or part of the active/managed user");
- }
- if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
- throw new IllegalArgumentException("device cannot have an invalid address");
- }
- if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.mDatabaseManager.getActiveAudioDevicePolicy(device);
- }
-
- @Override
- public int setMicrophonePreferredForCalls(
- BluetoothDevice device, boolean enabled, AttributionSource source) {
- requireNonNull(device);
- AdapterService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- if (!callerIsSystemOrActiveOrManagedUser(
- service, TAG, "setMicrophonePreferredForCalls")) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
- }
- if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
- throw new IllegalArgumentException("device cannot have an invalid address");
- }
- if (!Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService setMicrophonePreferredForCalls")) {
- return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.mDatabaseManager.setMicrophonePreferredForCalls(device, enabled);
- }
-
- @Override
- public boolean isMicrophonePreferredForCalls(
- BluetoothDevice device, AttributionSource source) {
- requireNonNull(device);
- AdapterService service = getService();
- if (service == null) {
- return true;
- }
- if (!callerIsSystemOrActiveOrManagedUser(
- service, TAG, "isMicrophonePreferredForCalls")) {
- throw new IllegalStateException(
- "Caller is not the system or part of the active/managed user");
- }
- if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
- throw new IllegalArgumentException("device cannot have an invalid address");
- }
- if (!Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService isMicrophonePreferredForCalls")) {
- return true;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.mDatabaseManager.isMicrophonePreferredForCalls(device);
- }
-
- @Override
- public boolean isLeCocSocketOffloadSupported(AttributionSource source) {
- AdapterService service = getService();
- if (service == null) {
- return false;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.isLeCocSocketOffloadSupported();
- }
-
- @Override
- public boolean isRfcommSocketOffloadSupported(AttributionSource source) {
- AdapterService service = getService();
- if (service == null) {
- return false;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.isRfcommSocketOffloadSupported();
- }
-
- @Override
- public IBinder getBluetoothAdvertise() {
- AdapterService service = getService();
- return service == null ? null : service.getBluetoothAdvertise();
- }
-
- @Override
- public IBinder getDistanceMeasurement() {
- AdapterService service = getService();
- return service == null ? null : service.getDistanceMeasurement();
- }
-
- @Override
- public int getKeyMissingCount(BluetoothDevice device, AttributionSource source) {
- AdapterService service = getService();
- if (service == null) {
- return -1;
- }
- if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "getKeyMissingCount")) {
- throw new IllegalStateException(
- "Caller is not the system or part of the active/managed user");
- }
- if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
- throw new IllegalArgumentException("device cannot have an invalid address");
- }
- if (!Utils.checkConnectPermissionForDataDelivery(
- service, source, "AdapterService getKeyMissingCount")) {
- return -1;
- }
-
- return service.mDatabaseManager.getKeyMissingCount(device);
- }
- }
-
- /**
* Gets the preferred audio profiles for the device. See {@link
* BluetoothAdapter#getPreferredAudioProfiles(BluetoothDevice)} for more details.
*
@@ -4449,7 +2265,7 @@ public class AdapterService extends Service {
* @param modeToProfileBundle is the preferences we want to set for the device
* @return whether the preferences were successfully requested
*/
- private int setPreferredAudioProfiles(BluetoothDevice device, Bundle modeToProfileBundle) {
+ int setPreferredAudioProfiles(BluetoothDevice device, Bundle modeToProfileBundle) {
Log.i(TAG, "setPreferredAudioProfiles for device=" + device);
if (!isDualModeAudioEnabled()) {
Log.e(TAG, "setPreferredAudioProfiles called while sysprop is disabled");
@@ -4669,7 +2485,7 @@ public class AdapterService extends Service {
* @param device the remote device whose preferred audio profiles have been changed
* @return whether the Bluetooth stack acknowledged the change successfully
*/
- private int notifyActiveDeviceChangeApplied(BluetoothDevice device) {
+ int notifyActiveDeviceChangeApplied(BluetoothDevice device) {
if (mLeAudioService == null) {
Log.e(TAG, "LE Audio profile not enabled");
return BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED;
@@ -4873,12 +2689,8 @@ public class AdapterService extends Service {
return Utils.getBytesFromAddress(deviceProp.getIdentityAddress());
}
- if (Flags.identityAddressNullIfNotKnown()) {
- // Return null if identity address unknown
- return null;
- } else {
- return Utils.getByteAddress(device);
- }
+ // Return null if identity address unknown
+ return null;
}
public BluetoothDevice getDeviceFromByte(byte[] address) {
@@ -4896,14 +2708,9 @@ public class AdapterService extends Service {
DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
if (deviceProp != null && deviceProp.getIdentityAddress() != null) {
return deviceProp.getIdentityAddress();
- } else {
- if (Flags.identityAddressNullIfNotKnown()) {
- // Return null if identity address unknown
- return null;
- } else {
- return address;
- }
}
+ // Return null if identity address unknown
+ return null;
}
/**
@@ -4929,16 +2736,21 @@ public class AdapterService extends Service {
}
identityAddressType = deviceProp.getIdentityAddressType();
} else {
- if (Flags.identityAddressNullIfNotKnown()) {
- identityAddress = null;
- } else {
- identityAddress = address;
- }
+ identityAddress = null;
}
return new BluetoothAddress(identityAddress, identityAddressType);
}
+ public boolean addAssociatedPackage(BluetoothDevice device, String packageName) {
+ DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
+ if (deviceProp == null) {
+ return false;
+ }
+ deviceProp.addPackage(packageName);
+ return true;
+ }
+
private record CallerInfo(String callerPackageName, UserHandle user) {}
boolean createBond(
@@ -5294,16 +3106,13 @@ public class AdapterService extends Service {
public int getConnectionState(BluetoothDevice device) {
final String address = device.getAddress();
- if (Flags.apiGetConnectionStateUsingIdentityAddress()) {
- int connectionState = mNativeInterface.getConnectionState(getBytesFromAddress(address));
- final String identityAddress = getIdentityAddress(address);
- if (identityAddress != null) {
- connectionState |=
- mNativeInterface.getConnectionState(getBytesFromAddress(identityAddress));
- }
- return connectionState;
+ int connectionState = mNativeInterface.getConnectionState(getBytesFromAddress(address));
+ final String identityAddress = getIdentityAddress(address);
+ if (identityAddress != null) {
+ connectionState |=
+ mNativeInterface.getConnectionState(getBytesFromAddress(identityAddress));
}
- return mNativeInterface.getConnectionState(getBytesFromAddress(address));
+ return connectionState;
}
int getConnectionHandle(BluetoothDevice device, int transport) {
@@ -5388,35 +3197,32 @@ public class AdapterService extends Service {
Log.e(TAG, "setActiveDevice: Bluetooth is not enabled");
return false;
}
- boolean setA2dp = false;
boolean setHeadset = false;
+ boolean setA2dp = false;
// Determine for which profiles we want to set device as our active device
switch (profiles) {
- case BluetoothAdapter.ACTIVE_DEVICE_AUDIO:
- setA2dp = true;
- break;
- case BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL:
+ case BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL -> setHeadset = true;
+ case BluetoothAdapter.ACTIVE_DEVICE_AUDIO -> setA2dp = true;
+ case BluetoothAdapter.ACTIVE_DEVICE_ALL -> {
setHeadset = true;
- break;
- case BluetoothAdapter.ACTIVE_DEVICE_ALL:
setA2dp = true;
- setHeadset = true;
- break;
- default:
+ }
+ default -> {
return false;
+ }
}
- boolean a2dpSupported =
- mA2dpService != null
- && (device == null
- || mA2dpService.getConnectionPolicy(device)
- == CONNECTION_POLICY_ALLOWED);
boolean hfpSupported =
mHeadsetService != null
&& (device == null
|| mHeadsetService.getConnectionPolicy(device)
== CONNECTION_POLICY_ALLOWED);
+ boolean a2dpSupported =
+ mA2dpService != null
+ && (device == null
+ || mA2dpService.getConnectionPolicy(device)
+ == CONNECTION_POLICY_ALLOWED);
boolean leAudioSupported =
mLeAudioService != null
&& (device == null
@@ -5439,6 +3245,12 @@ public class AdapterService extends Service {
}
}
+ // Order matters, some devices do not accept A2DP connection before HFP connection
+ if (setHeadset && hfpSupported) {
+ Log.i(TAG, "setActiveDevice: Setting active Headset " + device);
+ mHeadsetService.setActiveDevice(device);
+ }
+
if (setA2dp && a2dpSupported) {
Log.i(TAG, "setActiveDevice: Setting active A2dp device " + device);
if (device == null) {
@@ -5470,11 +3282,6 @@ public class AdapterService extends Service {
}
}
- if (setHeadset && hfpSupported) {
- Log.i(TAG, "setActiveDevice: Setting active Headset " + device);
- mHeadsetService.setActiveDevice(device);
- }
-
return true;
}
@@ -5489,8 +3296,8 @@ public class AdapterService extends Service {
if (mLeAudioService == null) {
return false;
}
- boolean a2dpSupported = isProfileSupported(leAudioDevice, BluetoothProfile.A2DP);
boolean hfpSupported = isProfileSupported(leAudioDevice, BluetoothProfile.HEADSET);
+ boolean a2dpSupported = isProfileSupported(leAudioDevice, BluetoothProfile.A2DP);
List<BluetoothDevice> groupDevices = mLeAudioService.getGroupDevices(leAudioDevice);
if (hfpSupported && mHeadsetService != null) {
@@ -5596,26 +3403,11 @@ public class AdapterService extends Service {
return BluetoothStatusCodes.SUCCESS;
}
- /**
- * Connect all supported bluetooth profiles between the local and remote device
- *
- * @param device is the remote device with which to connect all supported profiles
- */
+ /** All profile toggles are disabled, so connects all supported profiles */
void connectAllSupportedProfiles(BluetoothDevice device) {
int numProfilesConnected = 0;
- // All profile toggles disabled, so connects all supported profiles
- if (mA2dpService != null && isProfileSupported(device, BluetoothProfile.A2DP)) {
- Log.i(TAG, "connectAllSupportedProfiles: Connecting A2dp");
- // Set connection policy also connects the profile with CONNECTION_POLICY_ALLOWED
- mA2dpService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
- numProfilesConnected++;
- }
- if (mA2dpSinkService != null && isProfileSupported(device, BluetoothProfile.A2DP_SINK)) {
- Log.i(TAG, "connectAllSupportedProfiles: Connecting A2dp Sink");
- mA2dpSinkService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
- numProfilesConnected++;
- }
+ // Order matters, some devices do not accept A2DP connection before HFP connection
if (mHeadsetService != null && isProfileSupported(device, BluetoothProfile.HEADSET)) {
Log.i(TAG, "connectAllSupportedProfiles: Connecting Headset Profile");
mHeadsetService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
@@ -5627,6 +3419,17 @@ public class AdapterService extends Service {
mHeadsetClientService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
numProfilesConnected++;
}
+ if (mA2dpService != null && isProfileSupported(device, BluetoothProfile.A2DP)) {
+ Log.i(TAG, "connectAllSupportedProfiles: Connecting A2dp");
+ // Set connection policy also connects the profile with CONNECTION_POLICY_ALLOWED
+ mA2dpService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
+ numProfilesConnected++;
+ }
+ if (mA2dpSinkService != null && isProfileSupported(device, BluetoothProfile.A2DP_SINK)) {
+ Log.i(TAG, "connectAllSupportedProfiles: Connecting A2dp Sink");
+ mA2dpSinkService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
+ numProfilesConnected++;
+ }
if (mMapClientService != null && isProfileSupported(device, BluetoothProfile.MAP_CLIENT)) {
Log.i(TAG, "connectAllSupportedProfiles: Connecting MAP");
mMapClientService.setConnectionPolicy(device, CONNECTION_POLICY_ALLOWED);
@@ -5715,18 +3518,6 @@ public class AdapterService extends Service {
return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
}
- if (mA2dpService != null
- && (mA2dpService.getConnectionState(device) == STATE_CONNECTED
- || mA2dpService.getConnectionState(device) == STATE_CONNECTING)) {
- Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting A2dp");
- mA2dpService.disconnect(device);
- }
- if (mA2dpSinkService != null
- && (mA2dpSinkService.getConnectionState(device) == STATE_CONNECTED
- || mA2dpSinkService.getConnectionState(device) == STATE_CONNECTING)) {
- Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting A2dp Sink");
- mA2dpSinkService.disconnect(device);
- }
if (mHeadsetService != null
&& (mHeadsetService.getConnectionState(device) == STATE_CONNECTED
|| mHeadsetService.getConnectionState(device) == STATE_CONNECTING)) {
@@ -5739,6 +3530,18 @@ public class AdapterService extends Service {
Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting HFP");
mHeadsetClientService.disconnect(device);
}
+ if (mA2dpService != null
+ && (mA2dpService.getConnectionState(device) == STATE_CONNECTED
+ || mA2dpService.getConnectionState(device) == STATE_CONNECTING)) {
+ Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting A2dp");
+ mA2dpService.disconnect(device);
+ }
+ if (mA2dpSinkService != null
+ && (mA2dpSinkService.getConnectionState(device) == STATE_CONNECTED
+ || mA2dpSinkService.getConnectionState(device) == STATE_CONNECTING)) {
+ Log.i(TAG, "disconnectAllEnabledProfiles: Disconnecting A2dp Sink");
+ mA2dpSinkService.disconnect(device);
+ }
if (mMapClientService != null
&& (mMapClientService.getConnectionState(device) == STATE_CONNECTED
|| mMapClientService.getConnectionState(device) == STATE_CONNECTING)) {
@@ -6125,27 +3928,22 @@ public class AdapterService extends Service {
mLocalCallbacks.remove(callback);
}
- @VisibleForTesting
void registerRemoteCallback(IBluetoothCallback callback) {
mSystemServerCallbacks.register(callback);
}
- @VisibleForTesting
void unregisterRemoteCallback(IBluetoothCallback callback) {
mSystemServerCallbacks.unregister(callback);
}
- @VisibleForTesting
void bleOnToOn() {
mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_ON);
}
- @VisibleForTesting
void bleOnToOff() {
mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF);
}
- @VisibleForTesting
boolean factoryReset() {
mDatabaseManager.factoryReset();
@@ -6164,12 +3962,11 @@ public class AdapterService extends Service {
return mNativeInterface.factoryReset();
}
- @VisibleForTesting
int getScanMode() {
return mScanMode;
}
- private boolean setScanMode(int mode, String from) {
+ boolean setScanMode(int mode, String from) {
mScanModeChanges.add(from + ": " + scanModeName(mode));
if (!mNativeInterface.setScanMode(convertScanModeToHal(mode))) {
return false;
@@ -6183,7 +3980,6 @@ public class AdapterService extends Service {
return true;
}
- @VisibleForTesting
BluetoothActivityEnergyInfo reportActivityInfo() {
if (mAdapterProperties.getState() != BluetoothAdapter.STATE_ON
|| !mAdapterProperties.isActivityAndEnergyReportingSupported()) {
@@ -6398,12 +4194,12 @@ public class AdapterService extends Service {
/** Handle Bluetooth profiles when bond state changes with a {@link BluetoothDevice} */
public void handleBondStateChanged(BluetoothDevice device, int fromState, int toState) {
- if (mA2dpService != null && mA2dpService.isAvailable()) {
- mA2dpService.handleBondStateChanged(device, fromState, toState);
- }
if (mHeadsetService != null && mHeadsetService.isAvailable()) {
mHeadsetService.handleBondStateChanged(device, fromState, toState);
}
+ if (mA2dpService != null && mA2dpService.isAvailable()) {
+ mA2dpService.handleBondStateChanged(device, fromState, toState);
+ }
if (mLeAudioService != null && mLeAudioService.isAvailable()) {
mLeAudioService.handleBondStateChanged(device, fromState, toState);
}
@@ -6629,10 +4425,6 @@ public class AdapterService extends Service {
return BluetoothProperties.getHardwareOperatingVoltageMv().orElse(0) / 1000.0;
}
- public RemoteDevices getRemoteDevices() {
- return mRemoteDevices;
- }
-
private static String scanModeName(int scanMode) {
return switch (scanMode) {
case SCAN_MODE_NONE -> "SCAN_MODE_NONE";
diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterServiceBinder.java b/android/app/src/com/android/bluetooth/btservice/AdapterServiceBinder.java
new file mode 100644
index 0000000000..aff6642b7d
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/btservice/AdapterServiceBinder.java
@@ -0,0 +1,2262 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.btservice;
+
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.Manifest.permission.DUMP;
+import static android.Manifest.permission.LOCAL_MAC_ADDRESS;
+import static android.Manifest.permission.MODIFY_PHONE_STATE;
+import static android.bluetooth.BluetoothAdapter.SCAN_MODE_NONE;
+import static android.bluetooth.BluetoothDevice.TRANSPORT_AUTO;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+
+import static com.android.bluetooth.ChangeIds.ENFORCE_CONNECT;
+import static com.android.bluetooth.Utils.callerIsSystem;
+import static com.android.bluetooth.Utils.callerIsSystemOrActiveOrManagedUser;
+import static com.android.bluetooth.Utils.checkConnectPermissionForDataDelivery;
+import static com.android.bluetooth.Utils.checkScanPermissionForDataDelivery;
+import static com.android.bluetooth.Utils.getBytesFromAddress;
+import static com.android.bluetooth.Utils.getUidPidString;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
+import android.app.PendingIntent;
+import android.app.compat.CompatChanges;
+import android.bluetooth.BluetoothActivityEnergyInfo;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothAdapter.ActiveDeviceProfile;
+import android.bluetooth.BluetoothAdapter.ActiveDeviceUse;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothDevice.BluetoothAddress;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothProtoEnums;
+import android.bluetooth.BluetoothSinkAudioPolicy;
+import android.bluetooth.BluetoothStatusCodes;
+import android.bluetooth.IBluetooth;
+import android.bluetooth.IBluetoothActivityEnergyInfoListener;
+import android.bluetooth.IBluetoothCallback;
+import android.bluetooth.IBluetoothConnectionCallback;
+import android.bluetooth.IBluetoothHciVendorSpecificCallback;
+import android.bluetooth.IBluetoothMetadataListener;
+import android.bluetooth.IBluetoothOobDataCallback;
+import android.bluetooth.IBluetoothPreferredAudioProfilesCallback;
+import android.bluetooth.IBluetoothQualityReportReadyCallback;
+import android.bluetooth.IBluetoothSocketManager;
+import android.bluetooth.IncomingRfcommSocketInfo;
+import android.bluetooth.OobData;
+import android.content.AttributionSource;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.ParcelUuid;
+import android.os.Process;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.bluetooth.BluetoothStatsLog;
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties;
+import com.android.bluetooth.flags.Flags;
+import com.android.modules.expresslog.Counter;
+
+import libcore.util.SneakyThrow;
+
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
+
+/**
+ * There is no leak of this binder since it is never re-used and the process is systematically
+ * killed
+ */
+class AdapterServiceBinder extends IBluetooth.Stub {
+ private static final String TAG =
+ Utils.TAG_PREFIX_BLUETOOTH + AdapterServiceBinder.class.getSimpleName();
+
+ private static final int MIN_ADVT_INSTANCES_FOR_MA = 5;
+ private static final int MIN_OFFLOADED_FILTERS = 10;
+ private static final int MIN_OFFLOADED_SCAN_STORAGE_BYTES = 1024;
+
+ private final AdapterService mService;
+
+ AdapterServiceBinder(AdapterService svc) {
+ mService = svc;
+ }
+
+ public AdapterService getService() {
+ if (!mService.isAvailable()) {
+ return null;
+ }
+ return mService;
+ }
+
+ @Override
+ public int getState() {
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothAdapter.STATE_OFF;
+ }
+
+ return service.getState();
+ }
+
+ @Override
+ public void killBluetoothProcess() {
+ mService.enforceCallingPermission(BLUETOOTH_PRIVILEGED, null);
+
+ Runnable killAction =
+ () -> {
+ if (Flags.killInsteadOfExit()) {
+ Log.i(TAG, "killBluetoothProcess: Calling killProcess(myPid())");
+ Process.killProcess(Process.myPid());
+ } else {
+ Log.i(TAG, "killBluetoothProcess: Calling System.exit");
+ System.exit(0);
+ }
+ };
+
+ // Post on the main handler to let the cleanup complete before calling exit
+ mService.getHandler().post(killAction);
+
+ try {
+ // Wait for Bluetooth to be killed from its main thread
+ Thread.sleep(1_000); // SystemServer is waiting 2000 ms, we need to wait less here
+ } catch (InterruptedException e) {
+ Log.e(TAG, "killBluetoothProcess: Interrupted while waiting for kill");
+ }
+
+ // Bluetooth cannot be killed on the main thread; it is in a deadLock.
+ // Trying to recover by killing the Bluetooth from the binder thread.
+ // This is bad :(
+ Counter.logIncrement("bluetooth.value_kill_from_binder_thread");
+ Log.wtf(TAG, "Failed to kill Bluetooth using its main thread. Trying from binder");
+ killAction.run();
+ }
+
+ @Override
+ public void offToBleOn(boolean quietMode, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "offToBleOn")) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.offToBleOn(quietMode);
+ }
+
+ @Override
+ public void onToBleOn(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "onToBleOn")) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.onToBleOn();
+ }
+
+ @Override
+ public String getAddress(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getAddress")
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "getAddress")) {
+ return null;
+ }
+
+ service.enforceCallingOrSelfPermission(LOCAL_MAC_ADDRESS, null);
+ return Utils.getAddressStringFromByte(service.getAdapterProperties().getAddress());
+ }
+
+ @Override
+ public List<ParcelUuid> getUuids(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getUuids")
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "getUuids")) {
+ return Collections.emptyList();
+ }
+
+ ParcelUuid[] parcels = service.getAdapterProperties().getUuids();
+ if (parcels == null) {
+ parcels = new ParcelUuid[0];
+ }
+ return Arrays.asList(parcels);
+ }
+
+ @Override
+ public String getIdentityAddress(String address) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getIdentityAddress")
+ || !checkConnectPermissionForDataDelivery(
+ service,
+ Utils.getCallingAttributionSource(mService),
+ TAG,
+ "getIdentityAddress")) {
+ return null;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getIdentityAddress(address);
+ }
+
+ @Override
+ @NonNull
+ public BluetoothAddress getIdentityAddressWithType(@NonNull String address) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getIdentityAddressWithType")
+ || !checkConnectPermissionForDataDelivery(
+ service,
+ Utils.getCallingAttributionSource(mService),
+ TAG,
+ "getIdentityAddressWithType")) {
+ return new BluetoothAddress(null, BluetoothDevice.ADDRESS_TYPE_UNKNOWN);
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getIdentityAddressWithType(address);
+ }
+
+ @Override
+ public String getName(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getName")
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "getName")) {
+ return null;
+ }
+
+ return service.getName();
+ }
+
+ @Override
+ public int getNameLengthForAdvertise(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getNameLengthForAdvertise")
+ || !Utils.checkAdvertisePermissionForDataDelivery(service, source, TAG)) {
+ return -1;
+ }
+
+ return service.getNameLengthForAdvertise();
+ }
+
+ @Override
+ public boolean setName(String name, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setName")
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "setName")) {
+ return false;
+ }
+
+ if (Flags.emptyNamesAreInvalid()) {
+ requireNonNull(name);
+ name = name.trim();
+ if (name.isEmpty()) {
+ throw new IllegalArgumentException("Empty names are not valid");
+ }
+ }
+
+ Log.d(TAG, "AdapterServiceBinder.setName(" + name + ")");
+ return service.getAdapterProperties().setName(name);
+ }
+
+ @Override
+ public int getScanMode(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getScanMode")
+ || !checkScanPermissionForDataDelivery(service, source, TAG, "getScanMode")) {
+ return SCAN_MODE_NONE;
+ }
+
+ return service.getScanMode();
+ }
+
+ @Override
+ public int setScanMode(int mode, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setScanMode")
+ || !checkScanPermissionForDataDelivery(service, source, TAG, "setScanMode")) {
+ return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION;
+ }
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+
+ String logCaller = getUidPidString() + " packageName=" + source.getPackageName();
+ CompletableFuture<Boolean> future = new CompletableFuture<>();
+ mService.getHandler()
+ .post(
+ () ->
+ future.complete(
+ service.getState() == BluetoothAdapter.STATE_ON
+ && service.setScanMode(mode, logCaller)));
+ return future.join() ? BluetoothStatusCodes.SUCCESS : BluetoothStatusCodes.ERROR_UNKNOWN;
+ }
+
+ @Override
+ public long getDiscoverableTimeout(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getDiscoverableTimeout")
+ || !checkScanPermissionForDataDelivery(
+ service, source, TAG, "getDiscoverableTimeout")) {
+ return -1;
+ }
+
+ return service.getAdapterProperties().getDiscoverableTimeout();
+ }
+
+ @Override
+ public int setDiscoverableTimeout(long timeout, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setDiscoverableTimeout")
+ || !checkScanPermissionForDataDelivery(
+ service, source, TAG, "setDiscoverableTimeout")) {
+ return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getAdapterProperties().setDiscoverableTimeout((int) timeout)
+ ? BluetoothStatusCodes.SUCCESS
+ : BluetoothStatusCodes.ERROR_UNKNOWN;
+ }
+
+ @Override
+ public boolean startDiscovery(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "startDiscovery")
+ || !checkScanPermissionForDataDelivery(service, source, TAG, "startDiscovery")) {
+ return false;
+ }
+
+ Log.i(TAG, "startDiscovery: from " + getUidPidString());
+ return service.startDiscovery(source);
+ }
+
+ @Override
+ public boolean cancelDiscovery(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "cancelDiscovery")
+ || !checkScanPermissionForDataDelivery(service, source, TAG, "cancelDiscovery")) {
+ return false;
+ }
+
+ Log.i(TAG, "cancelDiscovery: from " + getUidPidString());
+ return service.getNative().cancelDiscovery();
+ }
+
+ @Override
+ public boolean isDiscovering(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "isDiscovering")
+ || !checkScanPermissionForDataDelivery(service, source, TAG, "isDiscovering")) {
+ return false;
+ }
+
+ return service.getAdapterProperties().isDiscovering();
+ }
+
+ @Override
+ public long getDiscoveryEndMillis(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getDiscoveryEndMillis")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "getDiscoveryEndMillis")) {
+ return -1;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+
+ return service.getAdapterProperties().discoveryEndMillis();
+ }
+
+ @Override
+ public List<BluetoothDevice> getMostRecentlyConnectedDevices(AttributionSource source) {
+ // don't check caller, may be called from system UI
+ AdapterService service = getService();
+ if (service == null
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "getMostRecentlyConnectedDevices")) {
+ return Collections.emptyList();
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+
+ return service.getDatabaseManager().getMostRecentlyConnectedDevices();
+ }
+
+ @Override
+ public List<BluetoothDevice> getBondedDevices(AttributionSource source) {
+ // don't check caller, may be called from system UI
+ AdapterService service = getService();
+ if (service == null
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "getBondedDevices")) {
+ return Collections.emptyList();
+ }
+
+ return Arrays.asList(service.getBondedDevices());
+ }
+
+ @Override
+ public int getAdapterConnectionState() {
+ // don't check caller, may be called from system UI
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothAdapter.STATE_DISCONNECTED;
+ }
+
+ return service.getAdapterProperties().getConnectionState();
+ }
+
+ /**
+ * This method has an associated binder cache. The invalidation methods must be changed if the
+ * logic behind this method changes.
+ */
+ @Override
+ public int getProfileConnectionState(int profile, AttributionSource source) {
+ AdapterService service = getService();
+ boolean checkConnect = false;
+ final int callingUid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ checkConnect = CompatChanges.isChangeEnabled(ENFORCE_CONNECT, callingUid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getProfileConnectionState")
+ || (checkConnect
+ && !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "getProfileConnectionState"))) {
+ return STATE_DISCONNECTED;
+ }
+
+ return service.getAdapterProperties().getProfileConnectionState(profile);
+ }
+
+ @Override
+ public boolean createBond(BluetoothDevice device, int transport, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "createBond")
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "createBond")) {
+ return false;
+ }
+
+ Log.i(
+ TAG,
+ "createBond:"
+ + (" device=" + device)
+ + (" transport=" + transport)
+ + (" from " + getUidPidString()));
+ return service.createBond(device, transport, null, null, source.getPackageName());
+ }
+
+ @Override
+ public boolean createBondOutOfBand(
+ BluetoothDevice device,
+ int transport,
+ OobData remoteP192Data,
+ OobData remoteP256Data,
+ AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "createBondOutOfBand")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "createBondOutOfBand")) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+
+ Log.i(
+ TAG,
+ "createBondOutOfBand:"
+ + (" device=" + device)
+ + (" transport=" + transport)
+ + (" from " + getUidPidString()));
+ return service.createBond(
+ device, transport, remoteP192Data, remoteP256Data, source.getPackageName());
+ }
+
+ @Override
+ public boolean cancelBondProcess(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "cancelBondProcess")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "cancelBondProcess")) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+
+ Log.i(TAG, "cancelBondProcess: device=" + device + ", from " + getUidPidString());
+
+ DeviceProperties deviceProp = service.getRemoteDevices().getDeviceProperties(device);
+ if (deviceProp != null) {
+ deviceProp.setBondingInitiatedLocally(false);
+ }
+
+ service.logUserBondResponse(device, false, source);
+ return service.getNative().cancelBond(getBytesFromAddress(device.getAddress()));
+ }
+
+ @Override
+ public boolean removeBond(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "removeBond")
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "removeBond")) {
+ return false;
+ }
+
+ Log.i(TAG, "removeBond: device=" + device + ", from " + getUidPidString());
+
+ DeviceProperties deviceProp = service.getRemoteDevices().getDeviceProperties(device);
+ if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) {
+ Log.w(
+ TAG,
+ device
+ + " cannot be removed since "
+ + ((deviceProp == null)
+ ? "properties are empty"
+ : "bond state is " + deviceProp.getBondState()));
+ return false;
+ }
+ service.logUserBondResponse(device, false, source);
+ service.getBondAttemptCallerInfo().remove(device.getAddress());
+ service.getPhonePolicy().ifPresent(policy -> policy.onRemoveBondRequest(device));
+ deviceProp.setBondingInitiatedLocally(false);
+
+ Message msg = service.getBondStateMachine().obtainMessage(BondStateMachine.REMOVE_BOND);
+ msg.obj = device;
+ service.getBondStateMachine().sendMessage(msg);
+ return true;
+ }
+
+ @Override
+ public int getBondState(BluetoothDevice device, AttributionSource source) {
+ // don't check caller, may be called from system UI
+ AdapterService service = getService();
+ if (service == null
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "getBondState")) {
+ return BluetoothDevice.BOND_NONE;
+ }
+
+ return service.getBondState(device);
+ }
+
+ @Override
+ public boolean isBondingInitiatedLocally(BluetoothDevice device, AttributionSource source) {
+ // don't check caller, may be called from system UI
+ AdapterService service = getService();
+ if (service == null
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "isBondingInitiatedLocally")) {
+ return false;
+ }
+
+ DeviceProperties deviceProp = service.getRemoteDevices().getDeviceProperties(device);
+ return deviceProp != null && deviceProp.isBondingInitiatedLocally();
+ }
+
+ @Override
+ public void generateLocalOobData(
+ int transport, IBluetoothOobDataCallback callback, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "generateLocalOobData")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "generateLocalOobData")) {
+ return;
+ }
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.generateLocalOobData(transport, callback);
+ }
+
+ @Override
+ public long getSupportedProfiles(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "getSupportedProfiles")) {
+ return 0;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return Config.getSupportedProfilesBitMask();
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "getConnectionState")) {
+ return BluetoothDevice.CONNECTION_STATE_DISCONNECTED;
+ }
+
+ return service.getConnectionState(device);
+ }
+
+ @Override
+ public int getConnectionHandle(
+ BluetoothDevice device, int transport, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getConnectionHandle")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "getConnectionHandle")) {
+ return BluetoothDevice.ERROR;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getConnectionHandle(device, transport);
+ }
+
+ @Override
+ public boolean canBondWithoutDialog(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "canBondWithoutDialog")) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.canBondWithoutDialog(device);
+ }
+
+ @Override
+ public String getPackageNameOfBondingApplication(
+ BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+
+ if (service == null
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "getPackageNameOfBondingApplication")) {
+ return null;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getPackageNameOfBondingApplication(device);
+ }
+
+ @Override
+ public boolean removeActiveDevice(@ActiveDeviceUse int profiles, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "removeActiveDevice")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "removeActiveDevice")) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+
+ Log.i(TAG, "removeActiveDevice: profiles=" + profiles + ", from " + getUidPidString());
+ return service.setActiveDevice(null, profiles);
+ }
+
+ @Override
+ public boolean setActiveDevice(
+ BluetoothDevice device, @ActiveDeviceUse int profiles, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setActiveDevice")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "setActiveDevice")) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+
+ Log.i(
+ TAG,
+ "setActiveDevice: device="
+ + device
+ + ", profiles="
+ + profiles
+ + ", from "
+ + getUidPidString());
+
+ return service.setActiveDevice(device, profiles);
+ }
+
+ @Override
+ public List<BluetoothDevice> getActiveDevices(
+ @ActiveDeviceProfile int profile, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getActiveDevices")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "getActiveDevices")) {
+ return Collections.emptyList();
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getActiveDevices(profile);
+ }
+
+ @Override
+ public int connectAllEnabledProfiles(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null || !service.isEnabled()) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "connectAllEnabledProfiles")) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
+ }
+ if (device == null) {
+ throw new IllegalArgumentException("device cannot be null");
+ }
+ if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
+ throw new IllegalArgumentException("device cannot have an invalid address");
+ }
+ if (!checkConnectPermissionForDataDelivery(
+ service, source, TAG, "connectAllEnabledProfiles")) {
+ return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
+ }
+
+ service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+
+ Log.i(TAG, "connectAllEnabledProfiles: device=" + device + ", from " + getUidPidString());
+ MetricsLogger.getInstance()
+ .logBluetoothEvent(
+ device,
+ BluetoothStatsLog
+ .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__INITIATOR_CONNECTION,
+ BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__START,
+ source.getUid());
+
+ try {
+ return service.connectAllEnabledProfiles(device);
+ } catch (Exception e) {
+ Log.v(TAG, "connectAllEnabledProfiles() failed", e);
+ SneakyThrow.sneakyThrow(e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public int disconnectAllEnabledProfiles(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "disconnectAllEnabledProfiles")) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
+ }
+ if (device == null) {
+ throw new IllegalArgumentException("device cannot be null");
+ }
+ if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
+ throw new IllegalArgumentException("device cannot have an invalid address");
+ }
+ if (!checkConnectPermissionForDataDelivery(
+ service, source, TAG, "disconnectAllEnabledProfiles")) {
+ return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+
+ Log.i(
+ TAG,
+ "disconnectAllEnabledProfiles: device=" + device + ", from " + getUidPidString());
+
+ try {
+ return service.disconnectAllEnabledProfiles(device);
+ } catch (Exception e) {
+ Log.v(TAG, "disconnectAllEnabledProfiles() failed", e);
+ SneakyThrow.sneakyThrow(e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public String getRemoteName(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteName")
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "getRemoteName")) {
+ return null;
+ }
+
+ return service.getRemoteName(device);
+ }
+
+ @Override
+ public int getRemoteType(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteType")
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "getRemoteType")) {
+ return BluetoothDevice.DEVICE_TYPE_UNKNOWN;
+ }
+
+ return service.getRemoteType(device);
+ }
+
+ @Override
+ public String getRemoteAlias(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteAlias")
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "getRemoteAlias")) {
+ return null;
+ }
+
+ DeviceProperties deviceProp = service.getRemoteDevices().getDeviceProperties(device);
+ return deviceProp != null ? deviceProp.getAlias() : null;
+ }
+
+ @Override
+ public int setRemoteAlias(BluetoothDevice device, String name, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setRemoteAlias")) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
+ }
+ if (name != null && name.isEmpty()) {
+ throw new IllegalArgumentException("alias cannot be the empty string");
+ }
+
+ if (!checkConnectPermissionForDataDelivery(service, source, TAG, "setRemoteAlias")) {
+ return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
+ }
+
+ Utils.enforceCdmAssociationIfNotBluetoothPrivileged(
+ service, service.getCompanionDeviceManager(), source, device);
+
+ DeviceProperties deviceProp = service.getRemoteDevices().getDeviceProperties(device);
+ if (deviceProp == null) {
+ return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED;
+ }
+ deviceProp.setAlias(device, name);
+ return BluetoothStatusCodes.SUCCESS;
+ }
+
+ @Override
+ public int getRemoteClass(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteClass")
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "getRemoteClass")) {
+ return 0;
+ }
+
+ return service.getRemoteClass(device);
+ }
+
+ @Override
+ public List<ParcelUuid> getRemoteUuids(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteUuids")
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "getRemoteUuids")) {
+ return Collections.emptyList();
+ }
+
+ final ParcelUuid[] parcels = service.getRemoteUuids(device);
+ if (parcels == null) {
+ return null;
+ }
+ return Arrays.asList(parcels);
+ }
+
+ @Override
+ public boolean fetchRemoteUuids(
+ BluetoothDevice device, int transport, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "fetchRemoteUuids")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "fetchRemoteUuids")) {
+ return false;
+ }
+ if (transport != TRANSPORT_AUTO) {
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ }
+
+ Log.i(
+ TAG,
+ "fetchRemoteUuids: device="
+ + device
+ + ", transport="
+ + transport
+ + ", from "
+ + getUidPidString());
+
+ service.getRemoteDevices().fetchUuids(device, transport);
+ MetricsLogger.getInstance().cacheCount(BluetoothProtoEnums.SDP_FETCH_UUID_REQUEST, 1);
+ return true;
+ }
+
+ @Override
+ public boolean setPin(
+ BluetoothDevice device,
+ boolean accept,
+ int len,
+ byte[] pinCode,
+ AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPin")
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "setPin")) {
+ return false;
+ }
+
+ DeviceProperties deviceProp = service.getRemoteDevices().getDeviceProperties(device);
+ // Only allow setting a pin in bonding state, or bonded state in case of security
+ // upgrade.
+ if (deviceProp == null || !deviceProp.isBondingOrBonded()) {
+ Log.e(TAG, "setPin: device=" + device + ", not bonding");
+ return false;
+ }
+ if (pinCode.length != len) {
+ android.util.EventLog.writeEvent(
+ 0x534e4554, "139287605", -1, "PIN code length mismatch");
+ return false;
+ }
+ service.logUserBondResponse(device, accept, source);
+ Log.i(
+ TAG,
+ "setPin: device=" + device + ", accept=" + accept + ", from " + getUidPidString());
+ return service.getNative()
+ .pinReply(getBytesFromAddress(device.getAddress()), accept, len, pinCode);
+ }
+
+ @Override
+ public boolean setPasskey(
+ BluetoothDevice device,
+ boolean accept,
+ int len,
+ byte[] passkey,
+ AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPasskey")
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "setPasskey")) {
+ return false;
+ }
+
+ DeviceProperties deviceProp = service.getRemoteDevices().getDeviceProperties(device);
+ if (deviceProp == null || !deviceProp.isBonding()) {
+ Log.e(TAG, "setPasskey: device=" + device + ", not bonding");
+ return false;
+ }
+ if (passkey.length != len) {
+ android.util.EventLog.writeEvent(
+ 0x534e4554, "139287605", -1, "Passkey length mismatch");
+ return false;
+ }
+ service.logUserBondResponse(device, accept, source);
+ Log.i(
+ TAG,
+ "setPasskey: device="
+ + device
+ + ", accept="
+ + accept
+ + ", from "
+ + getUidPidString());
+
+ return service.getNative()
+ .sspReply(
+ getBytesFromAddress(device.getAddress()),
+ AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY,
+ accept,
+ Utils.byteArrayToInt(passkey));
+ }
+
+ @Override
+ public boolean setPairingConfirmation(
+ BluetoothDevice device, boolean accept, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPairingConfirmation")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "setPairingConfirmation")) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+
+ DeviceProperties deviceProp = service.getRemoteDevices().getDeviceProperties(device);
+ if (deviceProp == null || !deviceProp.isBonding()) {
+ Log.e(TAG, "setPairingConfirmation: device=" + device + ", not bonding");
+ return false;
+ }
+ service.logUserBondResponse(device, accept, source);
+ Log.i(
+ TAG,
+ "setPairingConfirmation: device="
+ + device
+ + ", accept="
+ + accept
+ + ", from "
+ + getUidPidString());
+
+ return service.getNative()
+ .sspReply(
+ getBytesFromAddress(device.getAddress()),
+ AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION,
+ accept,
+ 0);
+ }
+
+ @Override
+ public boolean getSilenceMode(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getSilenceMode")
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "getSilenceMode")) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getSilenceDeviceManager().getSilenceMode(device);
+ }
+
+ @Override
+ public boolean setSilenceMode(
+ BluetoothDevice device, boolean silence, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setSilenceMode")
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "setSilenceMode")) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.getSilenceDeviceManager().setSilenceMode(device, silence);
+ return true;
+ }
+
+ @Override
+ public int getPhonebookAccessPermission(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(
+ service, TAG, "getPhonebookAccessPermission")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "getPhonebookAccessPermission")) {
+ return BluetoothDevice.ACCESS_UNKNOWN;
+ }
+
+ return service.getPhonebookAccessPermission(device);
+ }
+
+ @Override
+ public boolean setPhonebookAccessPermission(
+ BluetoothDevice device, int value, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(
+ service, TAG, "setPhonebookAccessPermission")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "setPhonebookAccessPermission")) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.setPhonebookAccessPermission(device, value);
+ return true;
+ }
+
+ @Override
+ public int getMessageAccessPermission(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getMessageAccessPermission")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "getMessageAccessPermission")) {
+ return BluetoothDevice.ACCESS_UNKNOWN;
+ }
+
+ return service.getMessageAccessPermission(device);
+ }
+
+ @Override
+ public boolean setMessageAccessPermission(
+ BluetoothDevice device, int value, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setMessageAccessPermission")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "setMessageAccessPermission")) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.setMessageAccessPermission(device, value);
+ return true;
+ }
+
+ @Override
+ public int getSimAccessPermission(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getSimAccessPermission")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "getSimAccessPermission")) {
+ return BluetoothDevice.ACCESS_UNKNOWN;
+ }
+
+ return service.getSimAccessPermission(device);
+ }
+
+ @Override
+ public boolean setSimAccessPermission(
+ BluetoothDevice device, int value, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setSimAccessPermission")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "setSimAccessPermission")) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.setSimAccessPermission(device, value);
+ return true;
+ }
+
+ @Override
+ public void logL2capcocServerConnection(
+ BluetoothDevice device,
+ int port,
+ boolean isSecured,
+ int result,
+ long socketCreationTimeMillis,
+ long socketCreationLatencyMillis,
+ long socketConnectionTimeMillis,
+ long timeoutMillis) {
+ AdapterService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.logL2capcocServerConnection(
+ device,
+ port,
+ isSecured,
+ result,
+ socketCreationTimeMillis,
+ socketCreationLatencyMillis,
+ socketConnectionTimeMillis,
+ timeoutMillis,
+ Binder.getCallingUid());
+ }
+
+ @Override
+ public IBluetoothSocketManager getSocketManager() {
+ AdapterService service = getService();
+ if (service == null) {
+ return null;
+ }
+
+ return IBluetoothSocketManager.Stub.asInterface(service.getBluetoothSocketManagerBinder());
+ }
+
+ @Override
+ public void logL2capcocClientConnection(
+ BluetoothDevice device,
+ int port,
+ boolean isSecured,
+ int result,
+ long socketCreationTimeNanos,
+ long socketCreationLatencyNanos,
+ long socketConnectionTimeNanos) {
+ AdapterService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.logL2capcocClientConnection(
+ device,
+ port,
+ isSecured,
+ result,
+ socketCreationTimeNanos,
+ socketCreationLatencyNanos,
+ socketConnectionTimeNanos,
+ Binder.getCallingUid());
+ }
+
+ @Override
+ public void logRfcommConnectionAttempt(
+ BluetoothDevice device,
+ boolean isSecured,
+ int resultCode,
+ long socketCreationTimeNanos,
+ boolean isSerialPort) {
+ AdapterService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.logRfcommConnectionAttempt(
+ device,
+ isSecured,
+ resultCode,
+ socketCreationTimeNanos,
+ isSerialPort,
+ Binder.getCallingUid());
+ }
+
+ @Override
+ public boolean sdpSearch(BluetoothDevice device, ParcelUuid uuid, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "sdpSearch")
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "sdpSearch")) {
+ return false;
+ }
+ return service.sdpSearch(device, uuid);
+ }
+
+ @Override
+ public int getBatteryLevel(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getBatteryLevel")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "getBatteryLevel")) {
+ return BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
+ }
+
+ DeviceProperties deviceProp = service.getRemoteDevices().getDeviceProperties(device);
+ if (deviceProp == null) {
+ return BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
+ }
+ return deviceProp.getBatteryLevel();
+ }
+
+ @Override
+ public int getMaxConnectedAudioDevices(AttributionSource source) {
+ // don't check caller, may be called from system UI
+ AdapterService service = getService();
+ if (service == null
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "getMaxConnectedAudioDevices")) {
+ return -1;
+ }
+
+ return service.getMaxConnectedAudioDevices();
+ }
+
+ @Override
+ public boolean factoryReset(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "factoryReset")) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.factoryReset();
+ }
+
+ @Override
+ public void registerBluetoothConnectionCallback(
+ IBluetoothConnectionCallback callback, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(
+ service, TAG, "registerBluetoothConnectionCallback")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "registerBluetoothConnectionCallback")) {
+ return;
+ }
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.getBluetoothConnectionCallbacks().register(callback);
+ }
+
+ @Override
+ public void unregisterBluetoothConnectionCallback(
+ IBluetoothConnectionCallback callback, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(
+ service, TAG, "unregisterBluetoothConnectionCallback")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "unregisterBluetoothConnectionCallback")) {
+ return;
+ }
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.getBluetoothConnectionCallbacks().unregister(callback);
+ }
+
+ @Override
+ public void registerCallback(IBluetoothCallback callback, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "registerCallback")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "registerCallback")) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.registerRemoteCallback(callback);
+ }
+
+ @Override
+ public void unregisterCallback(IBluetoothCallback callback, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "unregisterCallback")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "unregisterCallback")) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.unregisterRemoteCallback(callback);
+ }
+
+ @Override
+ public boolean isMultiAdvertisementSupported() {
+ AdapterService service = getService();
+ if (service == null) {
+ return false;
+ }
+
+ int val = service.getAdapterProperties().getNumOfAdvertisementInstancesSupported();
+ return val >= MIN_ADVT_INSTANCES_FOR_MA;
+ }
+
+ /**
+ * This method has an associated binder cache. The invalidation methods must be changed if the
+ * logic behind this method changes.
+ */
+ @Override
+ public boolean isOffloadedFilteringSupported() {
+ AdapterService service = getService();
+ if (service == null) {
+ return false;
+ }
+
+ int val = service.getNumOfOffloadedScanFilterSupported();
+ return val >= MIN_OFFLOADED_FILTERS;
+ }
+
+ @Override
+ public boolean isOffloadedScanBatchingSupported() {
+ AdapterService service = getService();
+ if (service == null) {
+ return false;
+ }
+
+ int val = service.getOffloadedScanResultStorage();
+ return val >= MIN_OFFLOADED_SCAN_STORAGE_BYTES;
+ }
+
+ @Override
+ public boolean isLe2MPhySupported() {
+ AdapterService service = getService();
+ if (service == null) {
+ return false;
+ }
+
+ return service.isLe2MPhySupported();
+ }
+
+ @Override
+ public boolean isLeCodedPhySupported() {
+ AdapterService service = getService();
+ if (service == null) {
+ return false;
+ }
+
+ return service.isLeCodedPhySupported();
+ }
+
+ @Override
+ public boolean isLeExtendedAdvertisingSupported() {
+ AdapterService service = getService();
+ if (service == null) {
+ return false;
+ }
+
+ return service.isLeExtendedAdvertisingSupported();
+ }
+
+ @Override
+ public boolean isLePeriodicAdvertisingSupported() {
+ AdapterService service = getService();
+ if (service == null) {
+ return false;
+ }
+
+ return service.isLePeriodicAdvertisingSupported();
+ }
+
+ @Override
+ public int isLeAudioSupported() {
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+
+ Set<Integer> supportedProfileServices =
+ Arrays.stream(Config.getSupportedProfiles()).boxed().collect(Collectors.toSet());
+ int[] leAudioUnicastProfiles = Config.getLeAudioUnicastProfiles();
+
+ if (Arrays.stream(leAudioUnicastProfiles).allMatch(supportedProfileServices::contains)) {
+ return BluetoothStatusCodes.FEATURE_SUPPORTED;
+ }
+
+ return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
+ }
+
+ @Override
+ public int isLeAudioBroadcastSourceSupported() {
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+
+ long supportBitMask = Config.getSupportedProfilesBitMask();
+ if ((supportBitMask & (1 << BluetoothProfile.LE_AUDIO_BROADCAST)) != 0) {
+ return BluetoothStatusCodes.FEATURE_SUPPORTED;
+ }
+
+ return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
+ }
+
+ @Override
+ public int isLeAudioBroadcastAssistantSupported() {
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+
+ int[] supportedProfileServices = Config.getSupportedProfiles();
+
+ if (Arrays.stream(supportedProfileServices)
+ .anyMatch(
+ profileId -> profileId == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)) {
+ return BluetoothStatusCodes.FEATURE_SUPPORTED;
+ }
+
+ return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
+ }
+
+ @Override
+ public int isDistanceMeasurementSupported(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ } else if (!callerIsSystemOrActiveOrManagedUser(
+ service, TAG, "isDistanceMeasurementSupported")) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
+ } else if (!checkConnectPermissionForDataDelivery(
+ service, source, TAG, "isDistanceMeasurementSupported")) {
+ return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
+ }
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return BluetoothStatusCodes.FEATURE_SUPPORTED;
+ }
+
+ @Override
+ public int getLeMaximumAdvertisingDataLength() {
+ AdapterService service = getService();
+ if (service == null) {
+ return 0;
+ }
+
+ return service.getLeMaximumAdvertisingDataLength();
+ }
+
+ @Override
+ public boolean isActivityAndEnergyReportingSupported() {
+ AdapterService service = getService();
+ if (service == null) {
+ return false;
+ }
+
+ return service.getAdapterProperties().isActivityAndEnergyReportingSupported();
+ }
+
+ @Override
+ public BluetoothActivityEnergyInfo reportActivityInfo(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "reportActivityInfo")) {
+ return null;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.reportActivityInfo();
+ }
+
+ @Override
+ public boolean registerMetadataListener(
+ IBluetoothMetadataListener listener, BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+ requireNonNull(listener);
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "registerMetadataListener")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "registerMetadataListener")) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.getHandler()
+ .post(
+ () ->
+ service.getMetadataListeners()
+ .computeIfAbsent(device, k -> new RemoteCallbackList())
+ .register(listener));
+ return true;
+ }
+
+ @Override
+ public boolean unregisterMetadataListener(
+ IBluetoothMetadataListener listener, BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+ requireNonNull(listener);
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "unregisterMetadataListener")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "unregisterMetadataListener")) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.getHandler()
+ .post(
+ () ->
+ service.getMetadataListeners()
+ .computeIfPresent(
+ device,
+ (k, v) -> {
+ v.unregister(listener);
+ if (v.getRegisteredCallbackCount() == 0) {
+ return null;
+ }
+ return v;
+ }));
+ return true;
+ }
+
+ @Override
+ public boolean setMetadata(
+ BluetoothDevice device, int key, byte[] value, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setMetadata")
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "setMetadata")) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.setMetadata(device, key, value);
+ }
+
+ @Override
+ public byte[] getMetadata(BluetoothDevice device, int key, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getMetadata")
+ || !checkConnectPermissionForDataDelivery(service, source, TAG, "getMetadata")) {
+ return null;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getMetadata(device, key);
+ }
+
+ @Override
+ public int isRequestAudioPolicyAsSinkSupported(
+ BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(
+ service, TAG, "isRequestAudioPolicyAsSinkSupported")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "isRequestAudioPolicyAsSinkSupported")) {
+ return BluetoothStatusCodes.FEATURE_NOT_CONFIGURED;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.isRequestAudioPolicyAsSinkSupported(device);
+ }
+
+ @Override
+ public int requestAudioPolicyAsSink(
+ BluetoothDevice device, BluetoothSinkAudioPolicy policies, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ } else if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "requestAudioPolicyAsSink")) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
+ } else if (!checkConnectPermissionForDataDelivery(
+ service, source, TAG, "requestAudioPolicyAsSink")) {
+ return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.requestAudioPolicyAsSink(device, policies);
+ }
+
+ @Override
+ public BluetoothSinkAudioPolicy getRequestedAudioPolicyAsSink(
+ BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(
+ service, TAG, "getRequestedAudioPolicyAsSink")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "getRequestedAudioPolicyAsSink")) {
+ return null;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getRequestedAudioPolicyAsSink(device);
+ }
+
+ @Override
+ public void requestActivityInfo(
+ IBluetoothActivityEnergyInfoListener listener, AttributionSource source) {
+ BluetoothActivityEnergyInfo info = reportActivityInfo(source);
+ try {
+ listener.onBluetoothActivityEnergyInfoAvailable(info);
+ } catch (RemoteException e) {
+ Log.e(TAG, "onBluetoothActivityEnergyInfo: RemoteException", e);
+ }
+ }
+
+ @Override
+ public void bleOnToOn(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "bleOnToOn")) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.bleOnToOn();
+ }
+
+ @Override
+ public void bleOnToOff(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "bleOnToOff")) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.bleOnToOff();
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, String[] args) {
+ PrintWriter writer = new PrintWriter(new FileOutputStream(fd));
+ AdapterService service = getService();
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(DUMP, null);
+ service.dump(fd, writer, args);
+ writer.close();
+ }
+
+ @Override
+ public boolean allowLowLatencyAudio(boolean allowed, BluetoothDevice device) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "allowLowLatencyAudio")
+ || !checkConnectPermissionForDataDelivery(
+ service,
+ Utils.getCallingAttributionSource(service),
+ TAG,
+ "allowLowLatencyAudio")) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.allowLowLatencyAudio(allowed, device);
+ }
+
+ @Override
+ public int startRfcommListener(
+ String name, ParcelUuid uuid, PendingIntent pendingIntent, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "startRfcommListener")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "startRfcommListener")) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.startRfcommListener(name, uuid, pendingIntent, source);
+ }
+
+ @Override
+ public int stopRfcommListener(ParcelUuid uuid, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(service, TAG, "stopRfcommListener")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "stopRfcommListener")) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.stopRfcommListener(uuid, source);
+ }
+
+ @Override
+ public IncomingRfcommSocketInfo retrievePendingSocketForServiceRecord(
+ ParcelUuid uuid, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(
+ service, TAG, "retrievePendingSocketForServiceRecord")
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "retrievePendingSocketForServiceRecord")) {
+ return null;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.retrievePendingSocketForServiceRecord(uuid, source);
+ }
+
+ @Override
+ public void setForegroundUserId(int userId, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !checkConnectPermissionForDataDelivery(
+ service,
+ Utils.getCallingAttributionSource(mService),
+ TAG,
+ "setForegroundUserId")) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ Utils.setForegroundUserId(userId);
+ }
+
+ @Override
+ public int setPreferredAudioProfiles(
+ BluetoothDevice device, Bundle modeToProfileBundle, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setPreferredAudioProfiles")) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
+ }
+ requireNonNull(device);
+ requireNonNull(modeToProfileBundle);
+ if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
+ throw new IllegalArgumentException("device cannot have an invalid address");
+ }
+ if (service.getBondState(device) != BluetoothDevice.BOND_BONDED) {
+ return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED;
+ }
+ if (!checkConnectPermissionForDataDelivery(
+ service, source, TAG, "setPreferredAudioProfiles")) {
+ return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.setPreferredAudioProfiles(device, modeToProfileBundle);
+ }
+
+ @Override
+ public Bundle getPreferredAudioProfiles(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null) {
+ return Bundle.EMPTY;
+ }
+ if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "getPreferredAudioProfiles")) {
+ return Bundle.EMPTY;
+ }
+ requireNonNull(device);
+ if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
+ throw new IllegalArgumentException("device cannot have an invalid address");
+ }
+ if (service.getBondState(device) != BluetoothDevice.BOND_BONDED) {
+ return Bundle.EMPTY;
+ }
+ if (!checkConnectPermissionForDataDelivery(
+ service, source, TAG, "getPreferredAudioProfiles")) {
+ return Bundle.EMPTY;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getPreferredAudioProfiles(device);
+ }
+
+ @Override
+ public int notifyActiveDeviceChangeApplied(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ if (!callerIsSystem(TAG, "notifyActiveDeviceChangeApplied")) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
+ }
+ requireNonNull(device);
+ if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
+ throw new IllegalArgumentException("device cannot have an invalid address");
+ }
+ if (service.getBondState(device) != BluetoothDevice.BOND_BONDED) {
+ return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED;
+ }
+ if (!checkConnectPermissionForDataDelivery(
+ service, source, TAG, "notifyActiveDeviceChangeApplied")) {
+ return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.notifyActiveDeviceChangeApplied(device);
+ }
+
+ @Override
+ public int isDualModeAudioEnabled(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ if (!checkConnectPermissionForDataDelivery(
+ service, source, TAG, "isDualModeAudioEnabled")) {
+ return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ if (!Utils.isDualModeAudioEnabled()) {
+ return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
+ }
+
+ return BluetoothStatusCodes.SUCCESS;
+ }
+
+ @Override
+ public int registerPreferredAudioProfilesChangedCallback(
+ IBluetoothPreferredAudioProfilesCallback callback, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ if (!callerIsSystemOrActiveOrManagedUser(
+ service, TAG, "registerPreferredAudioProfilesChangedCallback")) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
+ }
+ requireNonNull(callback);
+ if (!checkConnectPermissionForDataDelivery(
+ service, source, TAG, "registerPreferredAudioProfilesChangedCallback")) {
+ return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ // If LE only mode is enabled, the dual mode audio feature is disabled
+ if (!Utils.isDualModeAudioEnabled()) {
+ return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED;
+ }
+
+ service.getPreferredAudioProfilesCallbacks().register(callback);
+ return BluetoothStatusCodes.SUCCESS;
+ }
+
+ @Override
+ public int unregisterPreferredAudioProfilesChangedCallback(
+ IBluetoothPreferredAudioProfilesCallback callback, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ if (!callerIsSystemOrActiveOrManagedUser(
+ service, TAG, "unregisterPreferredAudioProfilesChangedCallback")) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
+ }
+ requireNonNull(callback);
+ if (!checkConnectPermissionForDataDelivery(
+ service, source, TAG, "unregisterPreferredAudioProfilesChangedCallback")) {
+ return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ if (!service.getPreferredAudioProfilesCallbacks().unregister(callback)) {
+ Log.e(
+ TAG,
+ "unregisterPreferredAudioProfilesChangedCallback: callback was never "
+ + "registered");
+ return BluetoothStatusCodes.ERROR_CALLBACK_NOT_REGISTERED;
+ }
+ return BluetoothStatusCodes.SUCCESS;
+ }
+
+ @Override
+ public int registerBluetoothQualityReportReadyCallback(
+ IBluetoothQualityReportReadyCallback callback, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ if (!callerIsSystemOrActiveOrManagedUser(
+ service, TAG, "registerBluetoothQualityReportReadyCallback")) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
+ }
+ requireNonNull(callback);
+ if (!checkConnectPermissionForDataDelivery(
+ service, source, TAG, "registerBluetoothQualityReportReadyCallback")) {
+ return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.getBluetoothQualityReportReadyCallbacks().register(callback);
+ return BluetoothStatusCodes.SUCCESS;
+ }
+
+ @Override
+ public int unregisterBluetoothQualityReportReadyCallback(
+ IBluetoothQualityReportReadyCallback callback, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ if (!callerIsSystemOrActiveOrManagedUser(
+ service, TAG, "unregisterBluetoothQualityReportReadyCallback")) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
+ }
+ requireNonNull(callback);
+ if (!checkConnectPermissionForDataDelivery(
+ service, source, TAG, "unregisterBluetoothQualityReportReadyCallback")) {
+ return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ if (!service.getBluetoothQualityReportReadyCallbacks().unregister(callback)) {
+ Log.e(
+ TAG,
+ "unregisterBluetoothQualityReportReadyCallback: callback was never registered");
+ return BluetoothStatusCodes.ERROR_CALLBACK_NOT_REGISTERED;
+ }
+ return BluetoothStatusCodes.SUCCESS;
+ }
+
+ @Override
+ public void registerHciVendorSpecificCallback(
+ IBluetoothHciVendorSpecificCallback callback, int[] eventCodes) {
+ AdapterService service = getService();
+ if (service == null) {
+ return;
+ }
+ if (!callerIsSystemOrActiveOrManagedUser(
+ service, TAG, "registerHciVendorSpecificCallback")) {
+ throw new SecurityException("not allowed");
+ }
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ requireNonNull(callback);
+ requireNonNull(eventCodes);
+
+ Set<Integer> eventCodesSet = Arrays.stream(eventCodes).boxed().collect(Collectors.toSet());
+ if (eventCodesSet.stream()
+ .anyMatch((n) -> (n < 0) || (n >= 0x52 && n < 0x60) || (n > 0xff))) {
+ throw new IllegalArgumentException("invalid vendor-specific event code");
+ }
+
+ service.getBluetoothHciVendorSpecificDispatcher().register(callback, eventCodesSet);
+ }
+
+ @Override
+ public void unregisterHciVendorSpecificCallback(IBluetoothHciVendorSpecificCallback callback) {
+ AdapterService service = getService();
+ if (service == null) {
+ return;
+ }
+ if (!callerIsSystemOrActiveOrManagedUser(
+ service, TAG, "unregisterHciVendorSpecificCallback")) {
+ throw new SecurityException("not allowed");
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ requireNonNull(callback);
+ service.getBluetoothHciVendorSpecificDispatcher().unregister(callback);
+ }
+
+ @Override
+ public void sendHciVendorSpecificCommand(
+ int ocf, byte[] parameters, IBluetoothHciVendorSpecificCallback callback) {
+ AdapterService service = getService();
+ if (service == null) {
+ return;
+ }
+ if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "sendHciVendorSpecificCommand")) {
+ throw new SecurityException("not allowed");
+ }
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+
+ // Open this no-op android command for test purpose
+ int getVendorCapabilitiesOcf = 0x153;
+ if (ocf < 0
+ || (ocf >= 0x150 && ocf < 0x160 && ocf != getVendorCapabilitiesOcf)
+ || (ocf > 0x3ff)) {
+ throw new IllegalArgumentException("invalid vendor-specific event code");
+ }
+ requireNonNull(parameters);
+ if (parameters.length > 255) {
+ throw new IllegalArgumentException("Parameters size is too big");
+ }
+
+ Optional<byte[]> cookie =
+ service.getBluetoothHciVendorSpecificDispatcher().getRegisteredCookie(callback);
+ if (!cookie.isPresent()) {
+ Log.e(TAG, "send command without registered callback");
+ throw new IllegalStateException("callback not registered");
+ }
+
+ service.getBluetoothHciVendorSpecificNativeInterface()
+ .sendCommand(ocf, parameters, cookie.get());
+ }
+
+ @Override
+ public int getOffloadedTransportDiscoveryDataScanSupported(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !callerIsSystemOrActiveOrManagedUser(
+ service, TAG, "getOffloadedTransportDiscoveryDataScanSupported")
+ || !checkScanPermissionForDataDelivery(
+ service, source, TAG, "getOffloadedTransportDiscoveryDataScanSupported")) {
+ return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getOffloadedTransportDiscoveryDataScanSupported();
+ }
+
+ @Override
+ public boolean isMediaProfileConnected(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null
+ || !checkConnectPermissionForDataDelivery(
+ service, source, TAG, "isMediaProfileConnected")) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.isMediaProfileConnected();
+ }
+
+ @Override
+ public IBinder getBluetoothGatt() {
+ AdapterService service = getService();
+ return service == null ? null : service.getBluetoothGatt();
+ }
+
+ @Override
+ public IBinder getBluetoothScan() {
+ AdapterService service = getService();
+ return service == null ? null : service.getBluetoothScan();
+ }
+
+ @Override
+ public void unregAllGattClient(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.unregAllGattClient(source);
+ }
+
+ @Override
+ public IBinder getProfile(int profileId) {
+ AdapterService service = getService();
+ if (service == null) {
+ return null;
+ }
+
+ return service.getProfile(profileId);
+ }
+
+ @Override
+ public int setActiveAudioDevicePolicy(
+ BluetoothDevice device, int activeAudioDevicePolicy, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setActiveAudioDevicePolicy")) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
+ }
+ if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
+ throw new IllegalArgumentException("device cannot have an invalid address");
+ }
+ if (!checkConnectPermissionForDataDelivery(
+ service, source, TAG, "setActiveAudioDevicePolicy")) {
+ return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getDatabaseManager()
+ .setActiveAudioDevicePolicy(device, activeAudioDevicePolicy);
+ }
+
+ @Override
+ public int getActiveAudioDevicePolicy(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT;
+ }
+ if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "getActiveAudioDevicePolicy")) {
+ throw new IllegalStateException(
+ "Caller is not the system or part of the active/managed user");
+ }
+ if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
+ throw new IllegalArgumentException("device cannot have an invalid address");
+ }
+ if (!checkConnectPermissionForDataDelivery(
+ service, source, TAG, "getActiveAudioDevicePolicy")) {
+ return BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getDatabaseManager().getActiveAudioDevicePolicy(device);
+ }
+
+ @Override
+ public int setMicrophonePreferredForCalls(
+ BluetoothDevice device, boolean enabled, AttributionSource source) {
+ requireNonNull(device);
+ AdapterService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setMicrophonePreferredForCalls")) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
+ }
+ if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
+ throw new IllegalArgumentException("device cannot have an invalid address");
+ }
+ if (!checkConnectPermissionForDataDelivery(
+ service, source, TAG, "setMicrophonePreferredForCalls")) {
+ return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getDatabaseManager().setMicrophonePreferredForCalls(device, enabled);
+ }
+
+ @Override
+ public boolean isMicrophonePreferredForCalls(BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+ AdapterService service = getService();
+ if (service == null) {
+ return true;
+ }
+ if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "isMicrophonePreferredForCalls")) {
+ throw new IllegalStateException(
+ "Caller is not the system or part of the active/managed user");
+ }
+ if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
+ throw new IllegalArgumentException("device cannot have an invalid address");
+ }
+ if (!checkConnectPermissionForDataDelivery(
+ service, source, TAG, "isMicrophonePreferredForCalls")) {
+ return true;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getDatabaseManager().isMicrophonePreferredForCalls(device);
+ }
+
+ @Override
+ public boolean isLeCocSocketOffloadSupported(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null) {
+ return false;
+ }
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.isLeCocSocketOffloadSupported();
+ }
+
+ @Override
+ public boolean isRfcommSocketOffloadSupported(AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null) {
+ return false;
+ }
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.isRfcommSocketOffloadSupported();
+ }
+
+ @Override
+ public IBinder getBluetoothAdvertise() {
+ AdapterService service = getService();
+ return service == null ? null : service.getBluetoothAdvertise();
+ }
+
+ @Override
+ public IBinder getDistanceMeasurement() {
+ AdapterService service = getService();
+ return service == null ? null : service.getDistanceMeasurement();
+ }
+
+ @Override
+ public int getKeyMissingCount(BluetoothDevice device, AttributionSource source) {
+ AdapterService service = getService();
+ if (service == null) {
+ return -1;
+ }
+ if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "getKeyMissingCount")) {
+ throw new IllegalStateException(
+ "Caller is not the system or part of the active/managed user");
+ }
+ if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
+ throw new IllegalArgumentException("device cannot have an invalid address");
+ }
+ if (!checkConnectPermissionForDataDelivery(service, source, TAG, "getKeyMissingCount")) {
+ return -1;
+ }
+
+ return service.getDatabaseManager().getKeyMissingCount(device);
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/btservice/BluetoothSocketManagerBinder.java b/android/app/src/com/android/bluetooth/btservice/BluetoothSocketManagerBinder.java
index c9b1c82473..0bdebd30e5 100644
--- a/android/app/src/com/android/bluetooth/btservice/BluetoothSocketManagerBinder.java
+++ b/android/app/src/com/android/bluetooth/btservice/BluetoothSocketManagerBinder.java
@@ -29,7 +29,6 @@ import android.os.ParcelUuid;
import android.util.Log;
import com.android.bluetooth.Utils;
-import com.android.bluetooth.flags.Flags;
class BluetoothSocketManagerBinder extends IBluetoothSocketManager.Stub {
private static final String TAG = BluetoothSocketManagerBinder.class.getSimpleName();
@@ -58,10 +57,7 @@ class BluetoothSocketManagerBinder extends IBluetoothSocketManager.Stub {
return null;
}
- String brEdrAddress =
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getBrEdrAddress(device)
- : mService.getIdentityAddress(device.getAddress());
+ String brEdrAddress = Utils.getBrEdrAddress(device);
Log.i(
TAG,
@@ -118,10 +114,7 @@ class BluetoothSocketManagerBinder extends IBluetoothSocketManager.Stub {
mService.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
enforceSocketOffloadSupport(type);
}
- String brEdrAddress =
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getBrEdrAddress(device)
- : mService.getIdentityAddress(device.getAddress());
+ String brEdrAddress = Utils.getBrEdrAddress(device);
Log.i(
TAG,
@@ -286,7 +279,7 @@ class BluetoothSocketManagerBinder extends IBluetoothSocketManager.Stub {
|| !Utils.callerIsSystemOrActiveOrManagedUser(
service, TAG, "getL2capLocalChannelId")
|| !Utils.checkConnectPermissionForDataDelivery(
- service, source, "BluetoothSocketManagerBinder getL2capLocalChannelId")) {
+ service, source, TAG, "getL2capLocalChannelId")) {
return INVALID_CID;
}
service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
@@ -300,7 +293,7 @@ class BluetoothSocketManagerBinder extends IBluetoothSocketManager.Stub {
|| !Utils.callerIsSystemOrActiveOrManagedUser(
service, TAG, "getL2capRemoteChannelId")
|| !Utils.checkConnectPermissionForDataDelivery(
- service, source, "BluetoothSocketManagerBinder getL2capRemoteChannelId")) {
+ service, source, TAG, "getL2capRemoteChannelId")) {
return INVALID_CID;
}
service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
diff --git a/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java b/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java
index 644b52dc8a..f59e69a42d 100644
--- a/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java
+++ b/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java
@@ -37,6 +37,12 @@ import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVEN
import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_VOLUME_CONTROL;
import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__STATE_BONDED;
import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__STATE_NONE;
+import static com.android.bluetooth.BluetoothStatsLog.HEARING_DEVICE_ACTIVE_EVENT_REPORTED__DEVICE_TYPE__ASHA;
+import static com.android.bluetooth.BluetoothStatsLog.HEARING_DEVICE_ACTIVE_EVENT_REPORTED__DEVICE_TYPE__CLASSIC;
+import static com.android.bluetooth.BluetoothStatsLog.HEARING_DEVICE_ACTIVE_EVENT_REPORTED__DEVICE_TYPE__LE_AUDIO;
+import static com.android.bluetooth.BluetoothStatsLog.HEARING_DEVICE_ACTIVE_EVENT_REPORTED__TIME_PERIOD__DAY;
+import static com.android.bluetooth.BluetoothStatsLog.HEARING_DEVICE_ACTIVE_EVENT_REPORTED__TIME_PERIOD__MONTH;
+import static com.android.bluetooth.BluetoothStatsLog.HEARING_DEVICE_ACTIVE_EVENT_REPORTED__TIME_PERIOD__WEEK;
import static com.android.bluetooth.BtRestrictedStatsLog.RESTRICTED_BLUETOOTH_DEVICE_NAME_REPORTED;
import android.app.AlarmManager;
@@ -45,6 +51,7 @@ import android.bluetooth.BluetoothA2dpSink;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothAvrcpController;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHapClient;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHeadsetClient;
import android.bluetooth.BluetoothHearingAid;
@@ -60,11 +67,13 @@ import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothProtoEnums;
import android.bluetooth.BluetoothSap;
import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.SystemClock;
+import android.provider.Settings;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
@@ -87,11 +96,14 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
+import java.util.function.BiPredicate;
/** Class of Bluetooth Metrics */
public class MetricsLogger {
@@ -273,6 +285,7 @@ public class MetricsLogger {
filter.addAction(BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(BluetoothSap.ACTION_CONNECTION_STATE_CHANGED);
+ filter.addAction(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED);
mAdapterService.registerReceiver(mReceiver, filter);
}
@@ -285,9 +298,18 @@ public class MetricsLogger {
Log.w(TAG, "Received intent with null action");
return;
}
+ BluetoothDevice device =
+ intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
switch (action) {
case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
logConnectionStateChanges(BluetoothProfile.A2DP, intent);
+ if (state == BluetoothProfile.STATE_CONNECTED
+ && isMedicalDevice(device)) {
+ updateHearingDeviceActiveTime(
+ device,
+ HEARING_DEVICE_ACTIVE_EVENT_REPORTED__DEVICE_TYPE__CLASSIC);
+ }
break;
case BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED:
logConnectionStateChanges(BluetoothProfile.A2DP_SINK, intent);
@@ -297,12 +319,23 @@ public class MetricsLogger {
break;
case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED:
logConnectionStateChanges(BluetoothProfile.HEADSET, intent);
+ if (state == BluetoothProfile.STATE_CONNECTED
+ && isMedicalDevice(device)) {
+ updateHearingDeviceActiveTime(
+ device,
+ HEARING_DEVICE_ACTIVE_EVENT_REPORTED__DEVICE_TYPE__CLASSIC);
+ }
break;
case BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED:
logConnectionStateChanges(BluetoothProfile.HEADSET_CLIENT, intent);
break;
case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED:
logConnectionStateChanges(BluetoothProfile.HEARING_AID, intent);
+ if (state == BluetoothProfile.STATE_CONNECTED) {
+ updateHearingDeviceActiveTime(
+ device,
+ HEARING_DEVICE_ACTIVE_EVENT_REPORTED__DEVICE_TYPE__ASHA);
+ }
break;
case BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED:
logConnectionStateChanges(BluetoothProfile.HID_DEVICE, intent);
@@ -331,6 +364,14 @@ public class MetricsLogger {
case BluetoothSap.ACTION_CONNECTION_STATE_CHANGED:
logConnectionStateChanges(BluetoothProfile.SAP, intent);
break;
+ case BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED:
+ if (state == BluetoothProfile.STATE_CONNECTED) {
+ updateHearingDeviceActiveTime(
+ device,
+ HEARING_DEVICE_ACTIVE_EVENT_REPORTED__DEVICE_TYPE__LE_AUDIO
+ );
+ }
+ break;
default:
Log.w(TAG, "Received unknown intent " + intent);
break;
@@ -646,7 +687,8 @@ public class MetricsLogger {
int numOngoingScan,
boolean isScreenOn,
boolean isAppDead,
- int appImportance) {
+ int appImportance,
+ String attributionTag) {
BluetoothStatsLog.write(
BluetoothStatsLog.LE_APP_SCAN_STATE_CHANGED,
uids,
@@ -662,7 +704,8 @@ public class MetricsLogger {
numOngoingScan,
isScreenOn,
isAppDead,
- convertAppImportance(appImportance));
+ convertAppImportance(appImportance),
+ attributionTag);
}
/** Logs the radio scan stats with app attribution when the radio scan stopped. */
@@ -675,7 +718,8 @@ public class MetricsLogger {
long scanWindowMillis,
boolean isScreenOn,
long scanDurationMillis,
- int appImportance) {
+ int appImportance,
+ String attributionTag) {
BluetoothStatsLog.write(
BluetoothStatsLog.LE_RADIO_SCAN_STOPPED,
uids,
@@ -686,7 +730,8 @@ public class MetricsLogger {
scanWindowMillis,
isScreenOn,
scanDurationMillis,
- convertAppImportance(appImportance));
+ convertAppImportance(appImportance),
+ attributionTag);
}
/** Logs the advertise stats with app attribution when the advertise state changed. */
@@ -702,7 +747,8 @@ public class MetricsLogger {
boolean isExtendedAdv,
int instanceCount,
long advDurationMs,
- int appImportance) {
+ int appImportance,
+ String attributionTag) {
BluetoothStatsLog.write(
BluetoothStatsLog.LE_ADV_STATE_CHANGED,
uids,
@@ -716,7 +762,8 @@ public class MetricsLogger {
isExtendedAdv,
instanceCount,
advDurationMs,
- convertAppImportance(appImportance));
+ convertAppImportance(appImportance),
+ attributionTag);
}
protected String getAllowlistedDeviceNameHash(
@@ -909,4 +956,56 @@ public class MetricsLogger {
syncStatus,
getRemoteDeviceInfoProto(device, false));
}
+
+ void logHearingDeviceActiveEvent(BluetoothDevice device, int type, int timePeriod) {
+ BluetoothStatsLog.write(
+ BluetoothStatsLog.HEARING_DEVICE_ACTIVE_EVENT_REPORTED,
+ type,
+ timePeriod,
+ getRemoteDeviceInfoProto(device, true));
+ }
+
+ void updateHearingDeviceActiveTime(BluetoothDevice device, int deviceTypeProto) {
+ // Time comparison includes a +/- 1 hour tolerance to prevent data loss
+ updateLastActiveTime(
+ device,
+ deviceTypeProto,
+ HEARING_DEVICE_ACTIVE_EVENT_REPORTED__TIME_PERIOD__DAY,
+ "last_active_day",
+ (now, lastActive) -> now.isAfter(lastActive.plusDays(1).minusHours(1)));
+ updateLastActiveTime(
+ device,
+ deviceTypeProto,
+ HEARING_DEVICE_ACTIVE_EVENT_REPORTED__TIME_PERIOD__WEEK,
+ "last_active_week",
+ (now, lastActive) -> now.isAfter(lastActive.plusWeeks(1).minusHours(1)));
+ updateLastActiveTime(
+ device,
+ deviceTypeProto,
+ HEARING_DEVICE_ACTIVE_EVENT_REPORTED__TIME_PERIOD__MONTH,
+ "last_active_month",
+ (now, lastActive) -> now.isAfter(lastActive.plusMonths(1).minusHours(1)));
+ }
+
+ private void updateLastActiveTime(
+ BluetoothDevice device,
+ int deviceTypeProto,
+ int timePeriodProto,
+ String timePeriodSettingsKey,
+ BiPredicate<LocalDateTime, LocalDateTime> timeComparison) {
+ final ContentResolver contentResolver = mAdapterService.getContentResolver();
+ final String lastActive = Settings.Secure.getString(contentResolver, timePeriodSettingsKey);
+ final LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault());
+ if (lastActive == null || timeComparison.test(now, LocalDateTime.parse(lastActive))) {
+ Settings.Secure.putString(contentResolver, timePeriodSettingsKey, now.toString());
+ logHearingDeviceActiveEvent(device, deviceTypeProto, timePeriodProto);
+ }
+ }
+
+ private boolean isMedicalDevice(BluetoothDevice device) {
+ final String deviceName = mAdapterService.getRemoteName(device);
+ final List<String> wordBreakdownList = getWordBreakdownList(deviceName);
+ boolean isMedicalDevice = !getMatchedStringForMedicalDevice(wordBreakdownList).isEmpty();
+ return isMedicalDevice;
+ }
}
diff --git a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java
index 456545a42a..c49659863b 100644
--- a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java
+++ b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java
@@ -27,6 +27,7 @@ import static com.android.modules.utils.build.SdkLevel.isAtLeastV;
import static java.util.Objects.requireNonNullElseGet;
+import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.app.Activity;
@@ -43,8 +44,11 @@ import android.bluetooth.BluetoothProtoEnums;
import android.bluetooth.BluetoothSinkAudioPolicy;
import android.bluetooth.BluetoothUtils;
import android.bluetooth.IBluetoothConnectionCallback;
+import android.content.AttributionSource;
import android.content.Intent;
+import android.content.pm.Attribution;
import android.net.MacAddress;
+import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -64,9 +68,13 @@ import com.android.modules.utils.build.SdkLevel;
import java.nio.charset.StandardCharsets;
import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
@@ -329,6 +337,7 @@ public class RemoteDevices {
}
class DeviceProperties {
+ private static final int MAX_PACKAGE_NAMES = 4;
private String mName;
private byte[] mAddress;
private String mIdentityAddress;
@@ -354,6 +363,16 @@ public class RemoteDevices {
@VisibleForTesting boolean mHfpBatteryIndicator = false;
private BluetoothSinkAudioPolicy mAudioPolicy;
+ // LRU cache of package names associated to this device
+ private final Set<String> mPackages =
+ Collections.newSetFromMap(
+ new LinkedHashMap<String, Boolean>() {
+ // This is called on every add. Returning true removes the eldest entry.
+ protected boolean removeEldestEntry(Map.Entry<String, Boolean> eldest) {
+ return size() >= MAX_PACKAGE_NAMES;
+ }
+ });
+
DeviceProperties() {
mBondState = BluetoothDevice.BOND_NONE;
}
@@ -858,6 +877,22 @@ public class RemoteDevices {
return mModelName;
}
}
+
+ @NonNull
+ public String[] getPackages() {
+ synchronized (mObject) {
+ return mPackages.toArray(new String[0]);
+ }
+ }
+
+ public void addPackage(String packageName) {
+ synchronized (mObject) {
+ // Removing the package ensures that the LRU cache order is updated. Adding it back
+ // will make it the newest.
+ mPackages.remove(packageName);
+ mPackages.add(packageName);
+ }
+ }
}
private void sendUuidIntent(BluetoothDevice device, DeviceProperties prop, boolean success) {
@@ -1574,6 +1609,28 @@ public class RemoteDevices {
// Bond loss detected, add to the count.
mAdapterService.getDatabase().updateKeyMissingCount(bluetoothDevice, true);
+ // Some apps are not able to handle the key missing broadcast, so we need to remove
+ // the bond to prevent them from misbehaving.
+ // TODO (b/402854328): Remove when the misbehaving apps are updated
+ if (bondLossIopFixNeeded(bluetoothDevice)) {
+ DeviceProperties deviceProperties = getDeviceProperties(bluetoothDevice);
+ if (deviceProperties == null) {
+ return;
+ }
+ String[] packages = deviceProperties.getPackages();
+ if (packages.length == 0) {
+ return;
+ }
+
+ Log.w(
+ TAG,
+ "Removing "
+ + bluetoothDevice
+ + " on behalf of: "
+ + Arrays.toString(packages));
+ bluetoothDevice.removeBond();
+ }
+
if (Flags.keyMissingPublic()) {
mAdapterService.sendOrderedBroadcast(
intent,
@@ -1992,6 +2049,55 @@ public class RemoteDevices {
device, batteryChargeIndicatorToPercentage(batteryLevel), /* isBas= */ false);
}
+ private static final String[] BOND_LOSS_IOP_PACKAGES = {
+ "com.sjm.crmd.patientApp_Android", "com.abbott.crm.ngq.patient",
+ };
+
+ private static final Set<String> BOND_LOSS_IOP_DEVICE_NAMES = Set.of("CM", "DM");
+
+ // TODO (b/402854328): Remove when the misbehaving apps are updated
+ public boolean bondLossIopFixNeeded(BluetoothDevice device) {
+ DeviceProperties deviceProperties = getDeviceProperties(device);
+ if (deviceProperties == null) {
+ return false;
+ }
+
+ String deviceName = deviceProperties.getName();
+ if (deviceName == null) {
+ return false;
+ }
+
+ String[] packages = deviceProperties.getPackages();
+ if (packages.length == 0) {
+ return false;
+ }
+
+ if (!BOND_LOSS_IOP_DEVICE_NAMES.contains(deviceName)) {
+ return false;
+ }
+
+ for (String iopFixPackage : BOND_LOSS_IOP_PACKAGES) {
+ for (String packageName : packages) {
+ if (packageName.contains(iopFixPackage)
+ && !Utils.checkCallerTargetSdk(
+ mAdapterService, packageName, Build.VERSION_CODES.BAKLAVA)) {
+ Log.w(
+ TAG,
+ "bondLossIopFixNeeded(): "
+ + " IOP fix needed for "
+ + device
+ + " name: "
+ + deviceName
+ + " package: "
+ + packageName);
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
private static void errorLog(String msg) {
Log.e(TAG, msg);
}
diff --git a/android/app/src/com/android/bluetooth/btservice/SilenceDeviceManager.java b/android/app/src/com/android/bluetooth/btservice/SilenceDeviceManager.java
index 4acfefc0d8..90d9a4bee6 100644
--- a/android/app/src/com/android/bluetooth/btservice/SilenceDeviceManager.java
+++ b/android/app/src/com/android/bluetooth/btservice/SilenceDeviceManager.java
@@ -31,7 +31,6 @@ import android.util.Log;
import com.android.bluetooth.Utils;
import com.android.bluetooth.a2dp.A2dpService;
import com.android.bluetooth.hfp.HeadsetService;
-import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.HashMap;
@@ -205,7 +204,6 @@ public class SilenceDeviceManager {
mSilenceDevices.clear();
}
- @VisibleForTesting
boolean setSilenceMode(BluetoothDevice device, boolean silence) {
Log.d(TAG, "setSilenceMode: " + device + ", " + silence);
mHandler.obtainMessage(
diff --git a/android/app/src/com/android/bluetooth/content_profiles/OWNERS b/android/app/src/com/android/bluetooth/content_profiles/OWNERS
deleted file mode 100644
index 8f87191393..0000000000
--- a/android/app/src/com/android/bluetooth/content_profiles/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_content \ No newline at end of file
diff --git a/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java b/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java
index 2b49f467a8..7a6597f5b0 100644
--- a/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java
+++ b/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java
@@ -17,7 +17,6 @@
package com.android.bluetooth.csip;
-import static android.Manifest.permission.BLUETOOTH_CONNECT;
import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
@@ -31,7 +30,6 @@ import static java.util.Objects.requireNonNullElseGet;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
import android.bluetooth.BluetoothCsipSetCoordinator;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
@@ -40,7 +38,6 @@ import android.bluetooth.BluetoothUuid;
import android.bluetooth.IBluetoothCsipSetCoordinator;
import android.bluetooth.IBluetoothCsipSetCoordinatorCallback;
import android.bluetooth.IBluetoothCsipSetCoordinatorLockCallback;
-import android.content.AttributionSource;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
@@ -152,7 +149,7 @@ public class CsipSetCoordinatorService extends ProfileService {
@Override
protected IProfileServiceBinder initBinder() {
- return new BluetoothCsisBinder(this);
+ return new CsipSetCoordinatorServiceBinder(this);
}
@Override
@@ -991,171 +988,6 @@ public class CsipSetCoordinatorService extends ProfileService {
BluetoothProfile.CSIP_SET_COORDINATOR, device, fromState, toState);
}
- /** Binder object: must be a static class or memory leak may occur */
- @VisibleForTesting
- static class BluetoothCsisBinder extends IBluetoothCsipSetCoordinator.Stub
- implements IProfileServiceBinder {
- private CsipSetCoordinatorService mService;
-
- BluetoothCsisBinder(CsipSetCoordinatorService svc) {
- mService = svc;
- }
-
- @Override
- public void cleanup() {
- mService = null;
- }
-
- @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED})
- private CsipSetCoordinatorService getService(AttributionSource source) {
- // Cache mService because it can change while getService is called
- CsipSetCoordinatorService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service;
- }
-
- @Override
- public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
- requireNonNull(source);
-
- CsipSetCoordinatorService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- return service.getConnectedDevices();
- }
-
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(
- int[] states, AttributionSource source) {
- requireNonNull(source);
-
- CsipSetCoordinatorService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- return service.getDevicesMatchingConnectionStates(states);
- }
-
- @Override
- public int getConnectionState(BluetoothDevice device, AttributionSource source) {
- requireNonNull(device);
- requireNonNull(source);
-
- CsipSetCoordinatorService service = getService(source);
- if (service == null) {
- return STATE_DISCONNECTED;
- }
-
- return service.getConnectionState(device);
- }
-
- @Override
- public boolean setConnectionPolicy(
- BluetoothDevice device, int connectionPolicy, AttributionSource source) {
- requireNonNull(device);
- requireNonNull(source);
-
- CsipSetCoordinatorService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.setConnectionPolicy(device, connectionPolicy);
- }
-
- @Override
- public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
- requireNonNull(device);
- requireNonNull(source);
-
- CsipSetCoordinatorService service = getService(source);
- if (service == null) {
- return CONNECTION_POLICY_UNKNOWN;
- }
-
- return service.getConnectionPolicy(device);
- }
-
- @Override
- public ParcelUuid lockGroup(
- int groupId,
- @NonNull IBluetoothCsipSetCoordinatorLockCallback callback,
- AttributionSource source) {
- requireNonNull(callback);
- requireNonNull(source);
-
- CsipSetCoordinatorService service = getService(source);
- if (service == null) {
- return null;
- }
-
- UUID lockUuid = service.lockGroup(groupId, callback);
- return lockUuid == null ? null : new ParcelUuid(lockUuid);
- }
-
- @Override
- public void unlockGroup(@NonNull ParcelUuid lockUuid, AttributionSource source) {
- requireNonNull(lockUuid);
- requireNonNull(source);
-
- CsipSetCoordinatorService service = getService(source);
- if (service == null) {
- return;
- }
-
- service.unlockGroup(lockUuid.getUuid());
- }
-
- @Override
- public List<Integer> getAllGroupIds(ParcelUuid uuid, AttributionSource source) {
- requireNonNull(uuid);
- requireNonNull(source);
-
- CsipSetCoordinatorService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- return service.getAllGroupIds(uuid);
- }
-
- @Override
- public Map<Integer, ParcelUuid> getGroupUuidMapByDevice(
- BluetoothDevice device, AttributionSource source) {
- CsipSetCoordinatorService service = getService(source);
- if (service == null) {
- return null;
- }
-
- return service.getGroupUuidMapByDevice(device);
- }
-
- @Override
- public int getDesiredGroupSize(int groupId, AttributionSource source) {
- CsipSetCoordinatorService service = getService(source);
- if (service == null) {
- return IBluetoothCsipSetCoordinator.CSIS_GROUP_SIZE_UNKNOWN;
- }
-
- return service.getDesiredGroupSize(groupId);
- }
- }
-
@Override
public void dump(StringBuilder sb) {
super.dump(sb);
diff --git a/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorServiceBinder.java b/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorServiceBinder.java
new file mode 100644
index 0000000000..5b08c1983b
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorServiceBinder.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.csip;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.IBluetoothCsipSetCoordinator;
+import android.bluetooth.IBluetoothCsipSetCoordinatorLockCallback;
+import android.content.AttributionSource;
+import android.os.ParcelUuid;
+
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+class CsipSetCoordinatorServiceBinder extends IBluetoothCsipSetCoordinator.Stub
+ implements IProfileServiceBinder {
+ private static final String TAG = CsipSetCoordinatorServiceBinder.class.getSimpleName();
+
+ private CsipSetCoordinatorService mService;
+
+ CsipSetCoordinatorServiceBinder(CsipSetCoordinatorService svc) {
+ mService = svc;
+ }
+
+ @Override
+ public void cleanup() {
+ mService = null;
+ }
+
+ @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED})
+ private CsipSetCoordinatorService getService(AttributionSource source) {
+ CsipSetCoordinatorService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
+ || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
+ return null;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service;
+ }
+
+ @Override
+ public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
+ requireNonNull(source);
+
+ CsipSetCoordinatorService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getConnectedDevices();
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ int[] states, AttributionSource source) {
+ requireNonNull(source);
+
+ CsipSetCoordinatorService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getDevicesMatchingConnectionStates(states);
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+ requireNonNull(source);
+
+ CsipSetCoordinatorService service = getService(source);
+ if (service == null) {
+ return STATE_DISCONNECTED;
+ }
+ return service.getConnectionState(device);
+ }
+
+ @Override
+ public boolean setConnectionPolicy(
+ BluetoothDevice device, int connectionPolicy, AttributionSource source) {
+ requireNonNull(device);
+ requireNonNull(source);
+
+ CsipSetCoordinatorService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.setConnectionPolicy(device, connectionPolicy);
+ }
+
+ @Override
+ public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+ requireNonNull(source);
+
+ CsipSetCoordinatorService service = getService(source);
+ if (service == null) {
+ return CONNECTION_POLICY_UNKNOWN;
+ }
+ return service.getConnectionPolicy(device);
+ }
+
+ @Override
+ public ParcelUuid lockGroup(
+ int groupId,
+ @NonNull IBluetoothCsipSetCoordinatorLockCallback callback,
+ AttributionSource source) {
+ requireNonNull(callback);
+ requireNonNull(source);
+
+ CsipSetCoordinatorService service = getService(source);
+ if (service == null) {
+ return null;
+ }
+
+ UUID lockUuid = service.lockGroup(groupId, callback);
+ return lockUuid == null ? null : new ParcelUuid(lockUuid);
+ }
+
+ @Override
+ public void unlockGroup(@NonNull ParcelUuid lockUuid, AttributionSource source) {
+ requireNonNull(lockUuid);
+ requireNonNull(source);
+
+ CsipSetCoordinatorService service = getService(source);
+ if (service == null) {
+ return;
+ }
+ service.unlockGroup(lockUuid.getUuid());
+ }
+
+ @Override
+ public List<Integer> getAllGroupIds(ParcelUuid uuid, AttributionSource source) {
+ requireNonNull(uuid);
+ requireNonNull(source);
+
+ CsipSetCoordinatorService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getAllGroupIds(uuid);
+ }
+
+ @Override
+ public Map<Integer, ParcelUuid> getGroupUuidMapByDevice(
+ BluetoothDevice device, AttributionSource source) {
+ CsipSetCoordinatorService service = getService(source);
+ if (service == null) {
+ return null;
+ }
+ return service.getGroupUuidMapByDevice(device);
+ }
+
+ @Override
+ public int getDesiredGroupSize(int groupId, AttributionSource source) {
+ CsipSetCoordinatorService service = getService(source);
+ if (service == null) {
+ return IBluetoothCsipSetCoordinator.CSIS_GROUP_SIZE_UNKNOWN;
+ }
+ return service.getDesiredGroupSize(groupId);
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/csip/OWNERS b/android/app/src/com/android/bluetooth/csip/OWNERS
deleted file mode 100644
index a7d77894ba..0000000000
--- a/android/app/src/com/android/bluetooth/csip/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_leaudio
diff --git a/android/app/src/com/android/bluetooth/gatt/AppAdvertiseStats.java b/android/app/src/com/android/bluetooth/gatt/AppAdvertiseStats.java
index b9ebfad69f..44154b31bd 100644
--- a/android/app/src/com/android/bluetooth/gatt/AppAdvertiseStats.java
+++ b/android/app/src/com/android/bluetooth/gatt/AppAdvertiseStats.java
@@ -35,7 +35,6 @@ import androidx.annotation.VisibleForTesting;
import com.android.bluetooth.BluetoothStatsLog;
import com.android.bluetooth.btservice.MetricsLogger;
-import com.android.bluetooth.flags.Flags;
import java.time.Duration;
import java.time.Instant;
@@ -219,14 +218,13 @@ class AppAdvertiseStats {
}
void recordAdvertiseErrorCount(int status) {
- if (Flags.bleScanAdvMetricsRedesign()) {
- BluetoothStatsLog.write(
- BluetoothStatsLog.LE_ADV_ERROR_REPORTED,
- new int[] {mAppUid},
- new String[] {mAppName},
- BluetoothStatsLog.LE_ADV_ERROR_REPORTED__LE_ADV_OP_CODE__ERROR_CODE_ON_START,
- convertStatusCode(status));
- }
+ BluetoothStatsLog.write(
+ BluetoothStatsLog.LE_ADV_ERROR_REPORTED,
+ new int[] {mAppUid},
+ new String[] {mAppName},
+ BluetoothStatsLog.LE_ADV_ERROR_REPORTED__LE_ADV_OP_CODE__ERROR_CODE_ON_START,
+ convertStatusCode(status),
+ getAttributionTag());
MetricsLogger.getInstance().cacheCount(BluetoothProtoEnums.LE_ADV_ERROR_ON_START_COUNT, 1);
}
@@ -355,6 +353,10 @@ class AppAdvertiseStats {
mAppImportance = importance;
}
+ private String getAttributionTag() {
+ return mAttributionTag != null ? mAttributionTag : "";
+ }
+
private static void recordAdvertiseDurationCount(
Duration duration, boolean isConnectable, boolean inPeriodic) {
if (duration.compareTo(Duration.ofMinutes(1)) < 0) {
@@ -416,22 +418,21 @@ class AppAdvertiseStats {
}
private void recordAdvertiseEnableCount(boolean enable, int instanceCount, long durationMs) {
- if (Flags.bleScanAdvMetricsRedesign()) {
- MetricsLogger.getInstance()
- .logAdvStateChanged(
- new int[] {mAppUid},
- new String[] {mAppName},
- enable /* enabled */,
- convertAdvInterval(mInterval),
- convertTxPowerLevel(mTxPowerLevel),
- mConnectable,
- mPeriodicAdvertisingEnabled,
- mScanResponseData != null && mScannable /* hasScanResponse */,
- !mLegacy /* isExtendedAdv */,
- instanceCount,
- durationMs,
- mAppImportance);
- }
+ MetricsLogger.getInstance()
+ .logAdvStateChanged(
+ new int[] {mAppUid},
+ new String[] {mAppName},
+ enable /* enabled */,
+ convertAdvInterval(mInterval),
+ convertTxPowerLevel(mTxPowerLevel),
+ mConnectable,
+ mPeriodicAdvertisingEnabled,
+ mScanResponseData != null && mScannable /* hasScanResponse */,
+ !mLegacy /* isExtendedAdv */,
+ instanceCount,
+ durationMs,
+ mAppImportance,
+ getAttributionTag());
if (enable) {
MetricsLogger.getInstance().cacheCount(BluetoothProtoEnums.LE_ADV_COUNT_ENABLE, 1);
if (mConnectable) {
diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java
index aaa00b45df..10190b09ef 100644
--- a/android/app/src/com/android/bluetooth/gatt/GattService.java
+++ b/android/app/src/com/android/bluetooth/gatt/GattService.java
@@ -24,8 +24,8 @@ import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
import static android.bluetooth.BluetoothUtils.toAnonymizedAddress;
import static com.android.bluetooth.Utils.callbackToApp;
-import static com.android.bluetooth.Utils.callerIsSystemOrActiveOrManagedUser;
import static com.android.bluetooth.Utils.checkCallerTargetSdk;
+import static com.android.bluetooth.Utils.checkConnectPermissionForDataDelivery;
import static com.android.bluetooth.util.AttributionSourceUtil.getLastAttributionTag;
import static java.util.Objects.requireNonNull;
@@ -43,7 +43,6 @@ import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothProtoEnums;
import android.bluetooth.BluetoothStatusCodes;
-import android.bluetooth.IBluetoothGatt;
import android.bluetooth.IBluetoothGattCallback;
import android.bluetooth.IBluetoothGattServerCallback;
import android.companion.CompanionDeviceManager;
@@ -212,7 +211,7 @@ public class GattService extends ProfileService {
@Override
protected IProfileServiceBinder initBinder() {
- return new BluetoothGattBinder(this);
+ return new GattServiceBinder(this);
}
@Override
@@ -263,6 +262,10 @@ public class GattService extends ProfileService {
return mScanController;
}
+ CompanionDeviceManager getCompanionDeviceManager() {
+ return mCompanionDeviceManager;
+ }
+
@Override
protected void setTestModeEnabled(boolean enableTestMode) {
if (mScanController != null) {
@@ -330,479 +333,6 @@ public class GattService extends ProfileService {
}
}
- /** Handlers for incoming service calls */
- @VisibleForTesting
- static class BluetoothGattBinder extends IBluetoothGatt.Stub implements IProfileServiceBinder {
- private GattService mService;
-
- BluetoothGattBinder(GattService svc) {
- mService = svc;
- }
-
- @Override
- public void cleanup() {
- mService = null;
- }
-
- private GattService getService() {
- // Cache mService because it can change while getService is called
- GattService service = mService;
-
- if (service == null || !service.isAvailable()) {
- Log.e(TAG, "getService() - Service requested, but not available!");
- return null;
- }
-
- return service;
- }
-
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(
- int[] states, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return Collections.emptyList();
- }
- return service.getDevicesMatchingConnectionStates(states, source);
- }
-
- @Override
- public void registerClient(
- ParcelUuid uuid,
- IBluetoothGattCallback callback,
- boolean eattSupport,
- AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.registerClient(uuid.getUuid(), callback, eattSupport, source);
- }
-
- @Override
- public void unregisterClient(int clientIf, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.unregisterClient(
- clientIf, source, ContextMap.RemoveReason.REASON_UNREGISTER_CLIENT);
- }
-
- @Override
- public void clientConnect(
- int clientIf,
- String address,
- int addressType,
- boolean isDirect,
- int transport,
- boolean opportunistic,
- int phy,
- AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.clientConnect(
- clientIf,
- address,
- addressType,
- isDirect,
- transport,
- opportunistic,
- phy,
- source);
- }
-
- @Override
- public void clientDisconnect(int clientIf, String address, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.clientDisconnect(clientIf, address, source);
- }
-
- @Override
- public void clientSetPreferredPhy(
- int clientIf,
- String address,
- int txPhy,
- int rxPhy,
- int phyOptions,
- AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.clientSetPreferredPhy(clientIf, address, txPhy, rxPhy, phyOptions, source);
- }
-
- @Override
- public void clientReadPhy(int clientIf, String address, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.clientReadPhy(clientIf, address, source);
- }
-
- @Override
- public void refreshDevice(int clientIf, String address, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.refreshDevice(clientIf, address, source);
- }
-
- @Override
- public void discoverServices(int clientIf, String address, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.discoverServices(clientIf, address, source);
- }
-
- @Override
- public void discoverServiceByUuid(
- int clientIf, String address, ParcelUuid uuid, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.discoverServiceByUuid(clientIf, address, uuid.getUuid(), source);
- }
-
- @Override
- public void readCharacteristic(
- int clientIf, String address, int handle, int authReq, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.readCharacteristic(clientIf, address, handle, authReq, source);
- }
-
- @Override
- public void readUsingCharacteristicUuid(
- int clientIf,
- String address,
- ParcelUuid uuid,
- int startHandle,
- int endHandle,
- int authReq,
- AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.readUsingCharacteristicUuid(
- clientIf, address, uuid.getUuid(), startHandle, endHandle, authReq, source);
- }
-
- @Override
- public int writeCharacteristic(
- int clientIf,
- String address,
- int handle,
- int writeType,
- int authReq,
- byte[] value,
- AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
- }
- return service.writeCharacteristic(
- clientIf, address, handle, writeType, authReq, value, source);
- }
-
- @Override
- public void readDescriptor(
- int clientIf, String address, int handle, int authReq, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.readDescriptor(clientIf, address, handle, authReq, source);
- }
-
- @Override
- public int writeDescriptor(
- int clientIf,
- String address,
- int handle,
- int authReq,
- byte[] value,
- AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
- }
- return service.writeDescriptor(clientIf, address, handle, authReq, value, source);
- }
-
- @Override
- public void beginReliableWrite(int clientIf, String address, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.beginReliableWrite(clientIf, address, source);
- }
-
- @Override
- public void endReliableWrite(
- int clientIf, String address, boolean execute, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.endReliableWrite(clientIf, address, execute, source);
- }
-
- @Override
- public void registerForNotification(
- int clientIf,
- String address,
- int handle,
- boolean enable,
- AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.registerForNotification(clientIf, address, handle, enable, source);
- }
-
- @Override
- public void readRemoteRssi(int clientIf, String address, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.readRemoteRssi(clientIf, address, source);
- }
-
- @Override
- public void configureMTU(int clientIf, String address, int mtu, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.configureMTU(clientIf, address, mtu, source);
- }
-
- @Override
- public void connectionParameterUpdate(
- int clientIf, String address, int connectionPriority, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.connectionParameterUpdate(clientIf, address, connectionPriority, source);
- }
-
- @Override
- public void leConnectionUpdate(
- int clientIf,
- String address,
- int minConnectionInterval,
- int maxConnectionInterval,
- int peripheralLatency,
- int supervisionTimeout,
- int minConnectionEventLen,
- int maxConnectionEventLen,
- AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.leConnectionUpdate(
- clientIf,
- address,
- minConnectionInterval,
- maxConnectionInterval,
- peripheralLatency,
- supervisionTimeout,
- minConnectionEventLen,
- maxConnectionEventLen,
- source);
- }
-
- @Override
- public int subrateModeRequest(
- int clientIf, BluetoothDevice device, int subrateMode, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
- }
- if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "subrateModeRequest")) {
- return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
- }
-
- if (!Utils.checkConnectPermissionForDataDelivery(
- service, source, "GattService subrateModeRequest")) {
- return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
- }
-
- Utils.enforceCdmAssociationIfNotBluetoothPrivileged(
- service, service.mCompanionDeviceManager, source, device);
-
- if (subrateMode < BluetoothGatt.SUBRATE_REQUEST_MODE_BALANCED
- || subrateMode > BluetoothGatt.SUBRATE_REQUEST_MODE_LOW_POWER) {
- throw new IllegalArgumentException("Subrate Mode not within valid range");
- }
-
- requireNonNull(device);
- String address = device.getAddress();
- if (!BluetoothAdapter.checkBluetoothAddress(address)) {
- throw new IllegalArgumentException("Invalid device address: " + address);
- }
-
- return service.subrateModeRequest(clientIf, device, subrateMode);
- }
-
- @Override
- public void registerServer(
- ParcelUuid uuid,
- IBluetoothGattServerCallback callback,
- boolean eattSupport,
- AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.registerServer(uuid.getUuid(), callback, eattSupport, source);
- }
-
- @Override
- public void unregisterServer(int serverIf, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.unregisterServer(serverIf, source);
- }
-
- @Override
- public void serverConnect(
- int serverIf,
- String address,
- int addressType,
- boolean isDirect,
- int transport,
- AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.serverConnect(serverIf, address, addressType, isDirect, transport, source);
- }
-
- @Override
- public void serverDisconnect(int serverIf, String address, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.serverDisconnect(serverIf, address, source);
- }
-
- @Override
- public void serverSetPreferredPhy(
- int serverIf,
- String address,
- int txPhy,
- int rxPhy,
- int phyOptions,
- AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.serverSetPreferredPhy(serverIf, address, txPhy, rxPhy, phyOptions, source);
- }
-
- @Override
- public void serverReadPhy(int clientIf, String address, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.serverReadPhy(clientIf, address, source);
- }
-
- @Override
- public void addService(int serverIf, BluetoothGattService svc, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.addService(serverIf, svc, source);
- }
-
- @Override
- public void removeService(int serverIf, int handle, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.removeService(serverIf, handle, source);
- }
-
- @Override
- public void clearServices(int serverIf, AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.clearServices(serverIf, source);
- }
-
- @Override
- public void sendResponse(
- int serverIf,
- String address,
- int requestId,
- int status,
- int offset,
- byte[] value,
- AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.sendResponse(serverIf, address, requestId, status, offset, value, source);
- }
-
- @Override
- public int sendNotification(
- int serverIf,
- String address,
- int handle,
- boolean confirm,
- byte[] value,
- AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
- }
- return service.sendNotification(serverIf, address, handle, confirm, value, source);
- }
-
- @Override
- public void disconnectAll(AttributionSource source) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.disconnectAll(source);
- }
- }
-
/**************************************************************************
* Callback functions - CLIENT
*************************************************************************/
@@ -1426,8 +956,8 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
List<BluetoothDevice> getDevicesMatchingConnectionStates(
int[] states, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService getDevicesMatchingConnectionStates")) {
+ if (!checkConnectPermissionForDataDelivery(
+ this, source, TAG, "getDevicesMatchingConnectionStates")) {
return Collections.emptyList();
}
@@ -1492,12 +1022,10 @@ public class GattService extends ProfileService {
IBluetoothGattCallback callback,
boolean eatt_support,
AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService registerClient")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "registerClient")) {
return;
}
- if (Flags.gattClientDynamicAllocation()
- && mClientMap.countByAppUid(Binder.getCallingUid()) >= GATT_CLIENT_LIMIT_PER_APP) {
+ if (mClientMap.countByAppUid(Binder.getCallingUid()) >= GATT_CLIENT_LIMIT_PER_APP) {
Log.w(TAG, "registerClient() - failed due to too many clients");
callbackToApp(() -> callback.onClientRegistered(BluetoothGatt.GATT_FAILURE, 0));
return;
@@ -1522,8 +1050,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void unregisterClient(int clientIf, AttributionSource source, ContextMap.RemoveReason reason) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService unregisterClient")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "unregisterClient")) {
return;
}
@@ -1551,8 +1078,7 @@ public class GattService extends ProfileService {
boolean opportunistic,
int phy,
AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService clientConnect")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "clientConnect")) {
return;
}
@@ -1593,9 +1119,11 @@ public class GattService extends ProfileService {
int preferredMtu = 0;
- // Some applications expect MTU to be exchanged immediately on connections
String packageName = source.getPackageName();
if (packageName != null) {
+ mAdapterService.addAssociatedPackage(getDevice(address), packageName);
+
+ // Some apps expect MTU to be exchanged immediately on connections
for (Map.Entry<String, Integer> entry : EARLY_MTU_EXCHANGE_PACKAGES.entrySet()) {
if (packageName.contains(entry.getKey())) {
preferredMtu = entry.getValue();
@@ -1640,8 +1168,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void clientDisconnect(int clientIf, String address, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService clientDisconnect")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "clientDisconnect")) {
return;
}
@@ -1679,8 +1206,7 @@ public class GattService extends ProfileService {
int rxPhy,
int phyOptions,
AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService clientSetPreferredPhy")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "clientSetPreferredPhy")) {
return;
}
@@ -1703,8 +1229,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void clientReadPhy(int clientIf, String address, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService clientReadPhy")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "clientReadPhy")) {
return;
}
@@ -1722,8 +1247,8 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
synchronized List<ParcelUuid> getRegisteredServiceUuids(AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService getRegisteredServiceUuids")) {
+ if (!checkConnectPermissionForDataDelivery(
+ this, source, TAG, "getRegisteredServiceUuids")) {
return Collections.emptyList();
}
return mHandleMap.getEntries().stream()
@@ -1733,8 +1258,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
List<String> getConnectedDevices(AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService getConnectedDevices")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "getConnectedDevices")) {
return Collections.emptyList();
}
@@ -1747,8 +1271,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void refreshDevice(int clientIf, String address, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService refreshDevice")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "refreshDevice")) {
return;
}
@@ -1758,8 +1281,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void discoverServices(int clientIf, String address, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService discoverServices")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "discoverServices")) {
return;
}
@@ -1784,8 +1306,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void discoverServiceByUuid(int clientIf, String address, UUID uuid, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService discoverServiceByUuid")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "discoverServiceByUuid")) {
return;
}
@@ -1805,8 +1326,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void readCharacteristic(
int clientIf, String address, int handle, int authReq, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService readCharacteristic")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "readCharacteristic")) {
return;
}
@@ -1846,8 +1366,8 @@ public class GattService extends ProfileService {
int endHandle,
int authReq,
AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService readUsingCharacteristicUuid")) {
+ if (!checkConnectPermissionForDataDelivery(
+ this, source, TAG, "readUsingCharacteristicUuid")) {
return;
}
@@ -1893,8 +1413,7 @@ public class GattService extends ProfileService {
int authReq,
byte[] value,
AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService writeCharacteristic")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "writeCharacteristic")) {
return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
}
@@ -1939,8 +1458,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void readDescriptor(
int clientIf, String address, int handle, int authReq, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService readDescriptor")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "readDescriptor")) {
return;
}
@@ -1977,8 +1495,7 @@ public class GattService extends ProfileService {
int authReq,
byte[] value,
AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService writeDescriptor")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "writeDescriptor")) {
return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
}
Log.v(TAG, "writeDescriptor() - address=" + toAnonymizedAddress(address));
@@ -2000,8 +1517,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void beginReliableWrite(int clientIf, String address, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService beginReliableWrite")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "beginReliableWrite")) {
return;
}
@@ -2011,8 +1527,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void endReliableWrite(int clientIf, String address, boolean execute, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService endReliableWrite")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "endReliableWrite")) {
return;
}
@@ -2033,8 +1548,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void registerForNotification(
int clientIf, String address, int handle, boolean enable, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService registerForNotification")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "registerForNotification")) {
return;
}
@@ -2072,8 +1586,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void readRemoteRssi(int clientIf, String address, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService readRemoteRssi")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "readRemoteRssi")) {
return;
}
@@ -2083,8 +1596,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void configureMTU(int clientIf, String address, int mtu, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService configureMTU")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "configureMTU")) {
return;
}
@@ -2102,8 +1614,8 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void connectionParameterUpdate(
int clientIf, String address, int connectionPriority, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService connectionParameterUpdate")) {
+ if (!checkConnectPermissionForDataDelivery(
+ this, source, TAG, "connectionParameterUpdate")) {
return;
}
@@ -2150,8 +1662,7 @@ public class GattService extends ProfileService {
int minConnectionEventLen,
int maxConnectionEventLen,
AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService leConnectionUpdate")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "leConnectionUpdate")) {
return;
}
@@ -2184,7 +1695,7 @@ public class GattService extends ProfileService {
maxConnectionEventLen);
}
- private int subrateModeRequest(int clientIf, BluetoothDevice device, int subrateMode) {
+ int subrateModeRequest(int clientIf, BluetoothDevice device, int subrateMode) {
int subrateMin;
int subrateMax;
int maxLatency;
@@ -2612,8 +2123,7 @@ public class GattService extends ProfileService {
IBluetoothGattServerCallback callback,
boolean eatt_support,
AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService registerServer")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "registerServer")) {
return;
}
@@ -2625,8 +2135,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void unregisterServer(int serverIf, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService unregisterServer")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "unregisterServer")) {
return;
}
@@ -2646,8 +2155,7 @@ public class GattService extends ProfileService {
boolean isDirect,
int transport,
AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService serverConnect")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "serverConnect")) {
return;
}
@@ -2660,8 +2168,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void serverDisconnect(int serverIf, String address, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService serverDisconnect")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "serverDisconnect")) {
return;
}
@@ -2684,8 +2191,7 @@ public class GattService extends ProfileService {
int rxPhy,
int phyOptions,
AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService serverSetPreferredPhy")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "serverSetPreferredPhy")) {
return;
}
@@ -2708,8 +2214,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void serverReadPhy(int serverIf, String address, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService serverReadPhy")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "serverReadPhy")) {
return;
}
@@ -2727,7 +2232,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void addService(int serverIf, BluetoothGattService service, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(this, source, "GattService addService")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "addService")) {
return;
}
@@ -2772,8 +2277,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void removeService(int serverIf, int handle, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService removeService")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "removeService")) {
return;
}
@@ -2784,8 +2288,7 @@ public class GattService extends ProfileService {
@RequiresPermission(BLUETOOTH_CONNECT)
void clearServices(int serverIf, AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService clearServices")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "clearServices")) {
return;
}
@@ -2802,8 +2305,7 @@ public class GattService extends ProfileService {
int offset,
byte[] value,
AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService sendResponse")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "sendResponse")) {
return;
}
@@ -2817,21 +2319,14 @@ public class GattService extends ProfileService {
int handle = 0;
Integer connId = 0;
- if (!Flags.gattServerRequestsFix()) {
- HandleMap.Entry entry = mHandleMap.getByRequestId(requestId);
- if (entry != null) {
- handle = entry.mHandle;
- }
- connId = mServerMap.connIdByAddress(serverIf, address);
+ HandleMap.RequestData requestData = mHandleMap.getRequestDataByRequestId(requestId);
+ if (requestData != null) {
+ handle = requestData.handle();
+ connId = requestData.connId();
} else {
- HandleMap.RequestData requestData = mHandleMap.getRequestDataByRequestId(requestId);
- if (requestData != null) {
- handle = requestData.handle();
- connId = requestData.connId();
- } else {
- connId = mServerMap.connIdByAddress(serverIf, address);
- }
+ connId = mServerMap.connIdByAddress(serverIf, address);
}
+
mNativeInterface.gattServerSendResponse(
serverIf,
connId != null ? connId : 0,
@@ -2852,8 +2347,7 @@ public class GattService extends ProfileService {
boolean confirm,
byte[] value,
AttributionSource source) {
- if (!Utils.checkConnectPermissionForDataDelivery(
- this, source, "GattService sendNotification")) {
+ if (!checkConnectPermissionForDataDelivery(this, source, TAG, "sendNotification")) {
return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
}
diff --git a/android/app/src/com/android/bluetooth/gatt/GattServiceBinder.java b/android/app/src/com/android/bluetooth/gatt/GattServiceBinder.java
new file mode 100644
index 0000000000..7be287677c
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/gatt/GattServiceBinder.java
@@ -0,0 +1,499 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.gatt;
+
+import static com.android.bluetooth.Utils.callerIsSystemOrActiveOrManagedUser;
+import static com.android.bluetooth.Utils.checkConnectPermissionForDataDelivery;
+
+import static java.util.Objects.requireNonNull;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattService;
+import android.bluetooth.BluetoothStatusCodes;
+import android.bluetooth.IBluetoothGatt;
+import android.bluetooth.IBluetoothGattCallback;
+import android.bluetooth.IBluetoothGattServerCallback;
+import android.content.AttributionSource;
+import android.os.ParcelUuid;
+
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+
+import java.util.Collections;
+import java.util.List;
+
+/** Handlers for incoming service calls */
+class GattServiceBinder extends IBluetoothGatt.Stub implements IProfileServiceBinder {
+ private static final String TAG =
+ GattServiceConfig.TAG_PREFIX + GattServiceBinder.class.getSimpleName();
+
+ private GattService mService;
+
+ GattServiceBinder(GattService svc) {
+ mService = svc;
+ }
+
+ @Override
+ public void cleanup() {
+ mService = null;
+ }
+
+ private GattService getService() {
+ GattService service = mService;
+
+ if (!Utils.checkServiceAvailable(service, TAG)) {
+ return null;
+ }
+
+ return service;
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ int[] states, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getDevicesMatchingConnectionStates(states, source);
+ }
+
+ @Override
+ public void registerClient(
+ ParcelUuid uuid,
+ IBluetoothGattCallback callback,
+ boolean eattSupport,
+ AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.registerClient(uuid.getUuid(), callback, eattSupport, source);
+ }
+
+ @Override
+ public void unregisterClient(int clientIf, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.unregisterClient(
+ clientIf, source, ContextMap.RemoveReason.REASON_UNREGISTER_CLIENT);
+ }
+
+ @Override
+ public void clientConnect(
+ int clientIf,
+ String address,
+ int addressType,
+ boolean isDirect,
+ int transport,
+ boolean opportunistic,
+ int phy,
+ AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.clientConnect(
+ clientIf, address, addressType, isDirect, transport, opportunistic, phy, source);
+ }
+
+ @Override
+ public void clientDisconnect(int clientIf, String address, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.clientDisconnect(clientIf, address, source);
+ }
+
+ @Override
+ public void clientSetPreferredPhy(
+ int clientIf,
+ String address,
+ int txPhy,
+ int rxPhy,
+ int phyOptions,
+ AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.clientSetPreferredPhy(clientIf, address, txPhy, rxPhy, phyOptions, source);
+ }
+
+ @Override
+ public void clientReadPhy(int clientIf, String address, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.clientReadPhy(clientIf, address, source);
+ }
+
+ @Override
+ public void refreshDevice(int clientIf, String address, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.refreshDevice(clientIf, address, source);
+ }
+
+ @Override
+ public void discoverServices(int clientIf, String address, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.discoverServices(clientIf, address, source);
+ }
+
+ @Override
+ public void discoverServiceByUuid(
+ int clientIf, String address, ParcelUuid uuid, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.discoverServiceByUuid(clientIf, address, uuid.getUuid(), source);
+ }
+
+ @Override
+ public void readCharacteristic(
+ int clientIf, String address, int handle, int authReq, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.readCharacteristic(clientIf, address, handle, authReq, source);
+ }
+
+ @Override
+ public void readUsingCharacteristicUuid(
+ int clientIf,
+ String address,
+ ParcelUuid uuid,
+ int startHandle,
+ int endHandle,
+ int authReq,
+ AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.readUsingCharacteristicUuid(
+ clientIf, address, uuid.getUuid(), startHandle, endHandle, authReq, source);
+ }
+
+ @Override
+ public int writeCharacteristic(
+ int clientIf,
+ String address,
+ int handle,
+ int writeType,
+ int authReq,
+ byte[] value,
+ AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
+ }
+ return service.writeCharacteristic(
+ clientIf, address, handle, writeType, authReq, value, source);
+ }
+
+ @Override
+ public void readDescriptor(
+ int clientIf, String address, int handle, int authReq, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.readDescriptor(clientIf, address, handle, authReq, source);
+ }
+
+ @Override
+ public int writeDescriptor(
+ int clientIf,
+ String address,
+ int handle,
+ int authReq,
+ byte[] value,
+ AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
+ }
+ return service.writeDescriptor(clientIf, address, handle, authReq, value, source);
+ }
+
+ @Override
+ public void beginReliableWrite(int clientIf, String address, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.beginReliableWrite(clientIf, address, source);
+ }
+
+ @Override
+ public void endReliableWrite(
+ int clientIf, String address, boolean execute, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.endReliableWrite(clientIf, address, execute, source);
+ }
+
+ @Override
+ public void registerForNotification(
+ int clientIf, String address, int handle, boolean enable, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.registerForNotification(clientIf, address, handle, enable, source);
+ }
+
+ @Override
+ public void readRemoteRssi(int clientIf, String address, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.readRemoteRssi(clientIf, address, source);
+ }
+
+ @Override
+ public void configureMTU(int clientIf, String address, int mtu, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.configureMTU(clientIf, address, mtu, source);
+ }
+
+ @Override
+ public void connectionParameterUpdate(
+ int clientIf, String address, int connectionPriority, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.connectionParameterUpdate(clientIf, address, connectionPriority, source);
+ }
+
+ @Override
+ public void leConnectionUpdate(
+ int clientIf,
+ String address,
+ int minConnectionInterval,
+ int maxConnectionInterval,
+ int peripheralLatency,
+ int supervisionTimeout,
+ int minConnectionEventLen,
+ int maxConnectionEventLen,
+ AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.leConnectionUpdate(
+ clientIf,
+ address,
+ minConnectionInterval,
+ maxConnectionInterval,
+ peripheralLatency,
+ supervisionTimeout,
+ minConnectionEventLen,
+ maxConnectionEventLen,
+ source);
+ }
+
+ @Override
+ public int subrateModeRequest(
+ int clientIf, BluetoothDevice device, int subrateMode, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "subrateModeRequest")) {
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED;
+ }
+ if (!checkConnectPermissionForDataDelivery(service, source, TAG, "subrateModeRequest")) {
+ return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
+ }
+
+ Utils.enforceCdmAssociationIfNotBluetoothPrivileged(
+ service, service.getCompanionDeviceManager(), source, device);
+
+ if (subrateMode < BluetoothGatt.SUBRATE_REQUEST_MODE_BALANCED
+ || subrateMode > BluetoothGatt.SUBRATE_REQUEST_MODE_LOW_POWER) {
+ throw new IllegalArgumentException("Subrate Mode not within valid range");
+ }
+
+ requireNonNull(device);
+ String address = device.getAddress();
+ if (!BluetoothAdapter.checkBluetoothAddress(address)) {
+ throw new IllegalArgumentException("Invalid device address: " + address);
+ }
+
+ return service.subrateModeRequest(clientIf, device, subrateMode);
+ }
+
+ @Override
+ public void registerServer(
+ ParcelUuid uuid,
+ IBluetoothGattServerCallback callback,
+ boolean eattSupport,
+ AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.registerServer(uuid.getUuid(), callback, eattSupport, source);
+ }
+
+ @Override
+ public void unregisterServer(int serverIf, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.unregisterServer(serverIf, source);
+ }
+
+ @Override
+ public void serverConnect(
+ int serverIf,
+ String address,
+ int addressType,
+ boolean isDirect,
+ int transport,
+ AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.serverConnect(serverIf, address, addressType, isDirect, transport, source);
+ }
+
+ @Override
+ public void serverDisconnect(int serverIf, String address, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.serverDisconnect(serverIf, address, source);
+ }
+
+ @Override
+ public void serverSetPreferredPhy(
+ int serverIf,
+ String address,
+ int txPhy,
+ int rxPhy,
+ int phyOptions,
+ AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.serverSetPreferredPhy(serverIf, address, txPhy, rxPhy, phyOptions, source);
+ }
+
+ @Override
+ public void serverReadPhy(int clientIf, String address, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.serverReadPhy(clientIf, address, source);
+ }
+
+ @Override
+ public void addService(int serverIf, BluetoothGattService svc, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.addService(serverIf, svc, source);
+ }
+
+ @Override
+ public void removeService(int serverIf, int handle, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.removeService(serverIf, handle, source);
+ }
+
+ @Override
+ public void clearServices(int serverIf, AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.clearServices(serverIf, source);
+ }
+
+ @Override
+ public void sendResponse(
+ int serverIf,
+ String address,
+ int requestId,
+ int status,
+ int offset,
+ byte[] value,
+ AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.sendResponse(serverIf, address, requestId, status, offset, value, source);
+ }
+
+ @Override
+ public int sendNotification(
+ int serverIf,
+ String address,
+ int handle,
+ boolean confirm,
+ byte[] value,
+ AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
+ }
+ return service.sendNotification(serverIf, address, handle, confirm, value, source);
+ }
+
+ @Override
+ public void disconnectAll(AttributionSource source) {
+ GattService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.disconnectAll(source);
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/hap/HapClientService.java b/android/app/src/com/android/bluetooth/hap/HapClientService.java
index 731f3da90c..9b8092763c 100644
--- a/android/app/src/com/android/bluetooth/hap/HapClientService.java
+++ b/android/app/src/com/android/bluetooth/hap/HapClientService.java
@@ -159,7 +159,7 @@ public class HapClientService extends ProfileService {
@Override
protected IProfileServiceBinder initBinder() {
- return new HapClientBinder(this);
+ return new HapClientServiceBinder(this);
}
@Override
diff --git a/android/app/src/com/android/bluetooth/hap/HapClientBinder.java b/android/app/src/com/android/bluetooth/hap/HapClientServiceBinder.java
index eba1d9db4a..e036e43bb2 100644
--- a/android/app/src/com/android/bluetooth/hap/HapClientBinder.java
+++ b/android/app/src/com/android/bluetooth/hap/HapClientServiceBinder.java
@@ -36,21 +36,19 @@ import android.content.AttributionSource;
import android.util.Log;
import com.android.bluetooth.Utils;
-import com.android.bluetooth.btservice.ProfileService;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
import com.android.internal.annotations.VisibleForTesting;
import java.util.Collections;
import java.util.List;
-/** HapClientBinder class */
@VisibleForTesting
-class HapClientBinder extends IBluetoothHapClient.Stub
- implements ProfileService.IProfileServiceBinder {
- private static final String TAG = HapClientBinder.class.getSimpleName();
+class HapClientServiceBinder extends IBluetoothHapClient.Stub implements IProfileServiceBinder {
+ private static final String TAG = HapClientServiceBinder.class.getSimpleName();
private HapClientService mService;
- HapClientBinder(HapClientService svc) {
+ HapClientServiceBinder(HapClientService svc) {
mService = svc;
}
@@ -62,7 +60,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
@RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED})
private HapClientService getService(AttributionSource source) {
requireNonNull(source);
- // Cache mService because it can change while getService is called
HapClientService service = mService;
if (Utils.isInstrumentationTestMode()) {
@@ -86,7 +83,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
if (service == null) {
return Collections.emptyList();
}
-
return service.getConnectedDevices();
}
@@ -97,7 +93,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
if (service == null) {
return Collections.emptyList();
}
-
return service.getDevicesMatchingConnectionStates(states);
}
@@ -109,7 +104,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
}
requireNonNull(device);
-
return service.getConnectionState(device);
}
@@ -139,7 +133,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
}
requireNonNull(device);
-
return service.getConnectionPolicy(device);
}
@@ -151,7 +144,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
}
requireNonNull(device);
-
return service.getActivePresetIndex(device);
}
@@ -164,7 +156,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
}
requireNonNull(device);
-
return service.getActivePresetInfo(device);
}
@@ -176,7 +167,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
}
requireNonNull(device);
-
return service.getHapGroup(device);
}
@@ -188,7 +178,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
}
requireNonNull(device);
-
service.selectPreset(device, presetIndex);
}
@@ -198,7 +187,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
if (service == null) {
return;
}
-
service.selectPresetForGroup(groupId, presetIndex);
}
@@ -210,7 +198,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
}
requireNonNull(device);
-
service.switchToNextPreset(device);
}
@@ -220,7 +207,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
if (service == null) {
return;
}
-
service.switchToNextPresetForGroup(groupId);
}
@@ -232,7 +218,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
}
requireNonNull(device);
-
service.switchToPreviousPreset(device);
}
@@ -242,7 +227,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
if (service == null) {
return;
}
-
service.switchToPreviousPresetForGroup(groupId);
}
@@ -255,7 +239,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
}
requireNonNull(device);
-
return service.getPresetInfo(device, presetIndex);
}
@@ -268,7 +251,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
}
requireNonNull(device);
-
return service.getAllPresetInfo(device);
}
@@ -280,7 +262,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
}
requireNonNull(device);
-
return service.getFeatures(device);
}
@@ -294,7 +275,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
requireNonNull(device);
requireNonNull(name);
-
service.setPresetName(device, presetIndex, name);
}
@@ -307,7 +287,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
}
requireNonNull(name);
-
service.setPresetNameForGroup(groupId, presetIndex, name);
}
@@ -319,7 +298,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
}
requireNonNull(callback);
-
service.registerCallback(callback);
}
@@ -331,7 +309,6 @@ class HapClientBinder extends IBluetoothHapClient.Stub
}
requireNonNull(callback);
-
service.unregisterCallback(callback);
}
}
diff --git a/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java b/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java
index 6af6323083..0bf2650bb1 100644
--- a/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java
+++ b/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java
@@ -17,7 +17,6 @@
package com.android.bluetooth.hearingaid;
import static android.Manifest.permission.BLUETOOTH_CONNECT;
-import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
@@ -27,14 +26,11 @@ import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
import static java.util.Objects.requireNonNull;
-import android.annotation.RequiresPermission;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothHearingAid.AdvertisementServiceData;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
-import android.bluetooth.IBluetoothHearingAid;
-import android.content.AttributionSource;
import android.content.Intent;
import android.media.AudioDeviceCallback;
import android.media.AudioDeviceInfo;
@@ -57,7 +53,6 @@ import com.android.bluetooth.flags.Flags;
import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -130,7 +125,7 @@ public class HearingAidService extends ProfileService {
@Override
protected IProfileServiceBinder initBinder() {
- return new BluetoothHearingAidBinder(this);
+ return new HearingAidServiceBinder(this);
}
@Override
@@ -490,7 +485,7 @@ public class HearingAidService extends ProfileService {
return mDeviceCapabilitiesMap.getOrDefault(device, -1);
}
- private AdvertisementServiceData getAdvertisementServiceData(BluetoothDevice device) {
+ AdvertisementServiceData getAdvertisementServiceData(BluetoothDevice device) {
int capability = mAdapterService.getAshaCapability(device);
int id = mAdapterService.getAshaTruncatedHiSyncId(device);
if (capability < 0) {
@@ -855,213 +850,6 @@ public class HearingAidService extends ProfileService {
device, BluetoothProfile.HEARING_AID, toState, fromState);
}
- /** Binder object: must be a static class or memory leak may occur */
- @VisibleForTesting
- static class BluetoothHearingAidBinder extends IBluetoothHearingAid.Stub
- implements IProfileServiceBinder {
- private HearingAidService mService;
-
- BluetoothHearingAidBinder(HearingAidService svc) {
- mService = svc;
- }
-
- @Override
- public void cleanup() {
- mService = null;
- }
-
- @RequiresPermission(BLUETOOTH_CONNECT)
- private HearingAidService getService(AttributionSource source) {
- // Cache mService because it can change while getService is called
- HearingAidService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
- return service;
- }
-
- @Override
- public boolean connect(BluetoothDevice device, AttributionSource source) {
- HearingAidService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.connect(device);
- }
-
- @Override
- public boolean disconnect(BluetoothDevice device, AttributionSource source) {
- HearingAidService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.disconnect(device);
- }
-
- @Override
- public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
- HearingAidService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- return service.getConnectedDevices();
- }
-
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(
- int[] states, AttributionSource source) {
- HearingAidService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- return service.getDevicesMatchingConnectionStates(states);
- }
-
- @Override
- public int getConnectionState(BluetoothDevice device, AttributionSource source) {
- HearingAidService service = getService(source);
- if (service == null) {
- return STATE_DISCONNECTED;
- }
-
- return service.getConnectionState(device);
- }
-
- @Override
- public boolean setActiveDevice(BluetoothDevice device, AttributionSource source) {
- HearingAidService service = getService(source);
- if (service == null) {
- return false;
- }
-
- if (device == null) {
- return service.removeActiveDevice(false);
- } else {
- return service.setActiveDevice(device);
- }
- }
-
- @Override
- public List<BluetoothDevice> getActiveDevices(AttributionSource source) {
- HearingAidService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- return service.getActiveDevices();
- }
-
- @Override
- public boolean setConnectionPolicy(
- BluetoothDevice device, int connectionPolicy, AttributionSource source) {
- HearingAidService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.setConnectionPolicy(device, connectionPolicy);
- }
-
- @Override
- public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
- HearingAidService service = getService(source);
- if (service == null) {
- return CONNECTION_POLICY_UNKNOWN;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getConnectionPolicy(device);
- }
-
- @Override
- public void setVolume(int volume, AttributionSource source) {
- HearingAidService service = getService(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- service.setVolume(volume);
- }
-
- @Override
- public long getHiSyncId(BluetoothDevice device, AttributionSource source) {
- HearingAidService service = getService(source);
- if (service == null) {
- return BluetoothHearingAid.HI_SYNC_ID_INVALID;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getHiSyncId(device);
- }
-
- @Override
- public int getDeviceSide(BluetoothDevice device, AttributionSource source) {
- HearingAidService service = getService(source);
- if (service == null) {
- return BluetoothHearingAid.SIDE_UNKNOWN;
- }
-
- int side = service.getCapabilities(device);
- if (side != BluetoothHearingAid.SIDE_UNKNOWN) {
- side &= 1;
- }
-
- return side;
- }
-
- @Override
- public int getDeviceMode(BluetoothDevice device, AttributionSource source) {
- HearingAidService service = getService(source);
- if (service == null) {
- return BluetoothHearingAid.MODE_UNKNOWN;
- }
-
- int mode = service.getCapabilities(device);
- if (mode != BluetoothHearingAid.MODE_UNKNOWN) {
- mode = mode >> 1 & 1;
- }
-
- return mode;
- }
-
- @Override
- public AdvertisementServiceData getAdvertisementServiceData(
- BluetoothDevice device, AttributionSource source) {
- HearingAidService service = mService;
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
- || !Utils.checkScanPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getAdvertisementServiceData(device);
- }
- }
-
@Override
public void dump(StringBuilder sb) {
super.dump(sb);
diff --git a/android/app/src/com/android/bluetooth/hearingaid/HearingAidServiceBinder.java b/android/app/src/com/android/bluetooth/hearingaid/HearingAidServiceBinder.java
new file mode 100644
index 0000000000..de384fba5c
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/hearingaid/HearingAidServiceBinder.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.hearingaid;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+
+import android.annotation.RequiresPermission;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothHearingAid.AdvertisementServiceData;
+import android.bluetooth.IBluetoothHearingAid;
+import android.content.AttributionSource;
+
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+
+import java.util.Collections;
+import java.util.List;
+
+class HearingAidServiceBinder extends IBluetoothHearingAid.Stub implements IProfileServiceBinder {
+ private static final String TAG = HearingAidServiceBinder.class.getSimpleName();
+
+ private HearingAidService mService;
+
+ HearingAidServiceBinder(HearingAidService svc) {
+ mService = svc;
+ }
+
+ @Override
+ public void cleanup() {
+ mService = null;
+ }
+
+ @RequiresPermission(BLUETOOTH_CONNECT)
+ private HearingAidService getService(AttributionSource source) {
+ HearingAidService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
+ || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
+ return null;
+ }
+ return service;
+ }
+
+ @Override
+ public boolean connect(BluetoothDevice device, AttributionSource source) {
+ HearingAidService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.connect(device);
+ }
+
+ @Override
+ public boolean disconnect(BluetoothDevice device, AttributionSource source) {
+ HearingAidService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.disconnect(device);
+ }
+
+ @Override
+ public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
+ HearingAidService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getConnectedDevices();
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ int[] states, AttributionSource source) {
+ HearingAidService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getDevicesMatchingConnectionStates(states);
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice device, AttributionSource source) {
+ HearingAidService service = getService(source);
+ if (service == null) {
+ return STATE_DISCONNECTED;
+ }
+ return service.getConnectionState(device);
+ }
+
+ @Override
+ public boolean setActiveDevice(BluetoothDevice device, AttributionSource source) {
+ HearingAidService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ if (device == null) {
+ return service.removeActiveDevice(false);
+ } else {
+ return service.setActiveDevice(device);
+ }
+ }
+
+ @Override
+ public List<BluetoothDevice> getActiveDevices(AttributionSource source) {
+ HearingAidService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getActiveDevices();
+ }
+
+ @Override
+ public boolean setConnectionPolicy(
+ BluetoothDevice device, int connectionPolicy, AttributionSource source) {
+ HearingAidService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.setConnectionPolicy(device, connectionPolicy);
+ }
+
+ @Override
+ public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
+ HearingAidService service = getService(source);
+ if (service == null) {
+ return CONNECTION_POLICY_UNKNOWN;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getConnectionPolicy(device);
+ }
+
+ @Override
+ public void setVolume(int volume, AttributionSource source) {
+ HearingAidService service = getService(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.setVolume(volume);
+ }
+
+ @Override
+ public long getHiSyncId(BluetoothDevice device, AttributionSource source) {
+ HearingAidService service = getService(source);
+ if (service == null) {
+ return BluetoothHearingAid.HI_SYNC_ID_INVALID;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getHiSyncId(device);
+ }
+
+ @Override
+ public int getDeviceSide(BluetoothDevice device, AttributionSource source) {
+ HearingAidService service = getService(source);
+ if (service == null) {
+ return BluetoothHearingAid.SIDE_UNKNOWN;
+ }
+
+ int side = service.getCapabilities(device);
+ if (side != BluetoothHearingAid.SIDE_UNKNOWN) {
+ side &= 1;
+ }
+
+ return side;
+ }
+
+ @Override
+ public int getDeviceMode(BluetoothDevice device, AttributionSource source) {
+ HearingAidService service = getService(source);
+ if (service == null) {
+ return BluetoothHearingAid.MODE_UNKNOWN;
+ }
+
+ int mode = service.getCapabilities(device);
+ if (mode != BluetoothHearingAid.MODE_UNKNOWN) {
+ mode = mode >> 1 & 1;
+ }
+
+ return mode;
+ }
+
+ @Override
+ public AdvertisementServiceData getAdvertisementServiceData(
+ BluetoothDevice device, AttributionSource source) {
+ HearingAidService service = mService;
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
+ || !Utils.checkScanPermissionForDataDelivery(
+ service, source, TAG, "getAdvertisementServiceData")) {
+ return null;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getAdvertisementServiceData(device);
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/hearingaid/OWNERS b/android/app/src/com/android/bluetooth/hearingaid/OWNERS
deleted file mode 100644
index bbaa85ddbb..0000000000
--- a/android/app/src/com/android/bluetooth/hearingaid/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_hearingaid
diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetNativeInterface.java b/android/app/src/com/android/bluetooth/hfp/HeadsetNativeInterface.java
index 9d819eca5b..e3816ed636 100644
--- a/android/app/src/com/android/bluetooth/hfp/HeadsetNativeInterface.java
+++ b/android/app/src/com/android/bluetooth/hfp/HeadsetNativeInterface.java
@@ -24,7 +24,6 @@ import android.util.Log;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AdapterService;
-import com.android.bluetooth.flags.Flags;
import com.android.internal.annotations.GuardedBy;
/**
@@ -84,16 +83,12 @@ public class HeadsetNativeInterface {
return mAdapterService.getDeviceFromByte(address);
}
- private byte[] getByteAddress(BluetoothDevice device) {
+ private static byte[] getByteAddress(BluetoothDevice device) {
if (device == null) {
// Set bt_stack's active device to default if java layer set active device to null
return Utils.getBytesFromAddress("00:00:00:00:00:00");
}
- if (Flags.identityAddressNullIfNotKnown()) {
- return Utils.getByteBrEdrAddress(device);
- } else {
- return mAdapterService.getByteIdentityAddress(device);
- }
+ return Utils.getByteBrEdrAddress(device);
}
void onConnectionStateChanged(int state, byte[] address) {
@@ -357,10 +352,11 @@ public class HeadsetNativeInterface {
* Start voice recognition
*
* @param device target headset
+ * @param sendResult whether a BVRA response should be sent
* @return True on success, False on failure
*/
- boolean startVoiceRecognition(BluetoothDevice device) {
- return startVoiceRecognitionNative(getByteAddress(device));
+ boolean startVoiceRecognition(BluetoothDevice device, boolean sendResult) {
+ return startVoiceRecognitionNative(getByteAddress(device), sendResult);
}
/**
@@ -561,7 +557,7 @@ public class HeadsetNativeInterface {
private native boolean isVoiceRecognitionSupportedNative(byte[] address);
- private native boolean startVoiceRecognitionNative(byte[] address);
+ private native boolean startVoiceRecognitionNative(byte[] address, boolean sendResult);
private native boolean stopVoiceRecognitionNative(byte[] address);
diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java
index 251f347ea2..c5ab1f8dde 100644
--- a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java
+++ b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java
@@ -17,8 +17,6 @@
package com.android.bluetooth.hfp;
import static android.Manifest.permission.BLUETOOTH_CONNECT;
-import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
-import static android.Manifest.permission.MODIFY_PHONE_STATE;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
@@ -33,15 +31,12 @@ import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothSinkAudioPolicy;
import android.bluetooth.BluetoothStatusCodes;
import android.bluetooth.BluetoothUuid;
-import android.bluetooth.IBluetoothHeadset;
-import android.content.AttributionSource;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -80,7 +75,6 @@ import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
@@ -237,7 +231,7 @@ public class HeadsetService extends ProfileService {
@Override
public IProfileServiceBinder initBinder() {
- return new BluetoothHeadsetBinder(this);
+ return new HeadsetServiceBinder(this);
}
@Override
@@ -516,303 +510,6 @@ public class HeadsetService extends ProfileService {
}
}
- /** Handlers for incoming service calls */
- @VisibleForTesting
- static class BluetoothHeadsetBinder extends IBluetoothHeadset.Stub
- implements IProfileServiceBinder {
- private HeadsetService mService;
-
- BluetoothHeadsetBinder(HeadsetService svc) {
- mService = svc;
- }
-
- @Override
- public void cleanup() {
- mService = null;
- }
-
- @RequiresPermission(BLUETOOTH_CONNECT)
- private HeadsetService getService(AttributionSource source) {
- // Cache mService because it can change while getService is called
- HeadsetService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
- return service;
- }
-
- @Override
- public boolean connect(BluetoothDevice device, AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
- return service.connect(device);
- }
-
- @Override
- public boolean disconnect(BluetoothDevice device, AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.disconnect(device);
- }
-
- @Override
- public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- return service.getConnectedDevices();
- }
-
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(
- int[] states, AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- return service.getDevicesMatchingConnectionStates(states);
- }
-
- @Override
- public int getConnectionState(BluetoothDevice device, AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return STATE_DISCONNECTED;
- }
-
- return service.getConnectionState(device);
- }
-
- @Override
- public boolean setConnectionPolicy(
- BluetoothDevice device, int connectionPolicy, AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.setConnectionPolicy(device, connectionPolicy);
- }
-
- @Override
- public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return CONNECTION_POLICY_UNKNOWN;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getConnectionPolicy(device);
- }
-
- @Override
- public boolean isNoiseReductionSupported(BluetoothDevice device, AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.isNoiseReductionSupported(device);
- }
-
- @Override
- public boolean isVoiceRecognitionSupported(
- BluetoothDevice device, AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.isVoiceRecognitionSupported(device);
- }
-
- @Override
- public boolean startVoiceRecognition(BluetoothDevice device, AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return false;
- }
-
- requireNonNull(device);
-
- return service.startVoiceRecognition(device);
- }
-
- @Override
- public boolean stopVoiceRecognition(BluetoothDevice device, AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.stopVoiceRecognition(device);
- }
-
- @Override
- public boolean isAudioConnected(BluetoothDevice device, AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.isAudioConnected(device);
- }
-
- @Override
- public int getAudioState(BluetoothDevice device, AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return BluetoothHeadset.STATE_AUDIO_DISCONNECTED;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getAudioState(device);
- }
-
- @Override
- public int connectAudio(AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.connectAudio();
- }
-
- @Override
- public int disconnectAudio(AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.disconnectAudio();
- }
-
- @Override
- public void setAudioRouteAllowed(boolean allowed, AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.setAudioRouteAllowed(allowed);
- }
-
- @Override
- public boolean getAudioRouteAllowed(AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getAudioRouteAllowed();
- }
-
- @Override
- public void setForceScoAudio(boolean forced, AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return;
- }
-
- service.setForceScoAudio(forced);
- }
-
- @Override
- public boolean startScoUsingVirtualVoiceCall(AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.startScoUsingVirtualVoiceCall();
- }
-
- @Override
- public boolean stopScoUsingVirtualVoiceCall(AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.stopScoUsingVirtualVoiceCall();
- }
-
- @Override
- public boolean sendVendorSpecificResultCode(
- BluetoothDevice device, String command, String arg, AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.sendVendorSpecificResultCode(device, command, arg);
- }
-
- @Override
- public boolean setActiveDevice(BluetoothDevice device, AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
-
- return service.setActiveDevice(device);
- }
-
- @Override
- public BluetoothDevice getActiveDevice(AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return null;
- }
-
- return service.getActiveDevice();
- }
-
- @Override
- public boolean isInbandRingingEnabled(AttributionSource source) {
- HeadsetService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.isInbandRingingEnabled();
- }
- }
-
// API methods
public static synchronized HeadsetService getHeadsetService() {
if (sHeadsetService == null) {
@@ -947,7 +644,6 @@ public class HeadsetService extends ProfileService {
* @param states an array of states from {@link BluetoothProfile}
* @return a list of devices matching the array of connection states
*/
- @VisibleForTesting
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
ArrayList<BluetoothDevice> devices = new ArrayList<>();
synchronized (mStateMachines) {
@@ -1659,7 +1355,6 @@ public class HeadsetService extends ProfileService {
}
}
- @VisibleForTesting
boolean startScoUsingVirtualVoiceCall() {
Log.i(TAG, "startScoUsingVirtualVoiceCall: " + Utils.getUidPidString());
synchronized (mStateMachines) {
@@ -2134,8 +1829,7 @@ public class HeadsetService extends ProfileService {
}
}
- private boolean sendVendorSpecificResultCode(
- BluetoothDevice device, String command, String arg) {
+ boolean sendVendorSpecificResultCode(BluetoothDevice device, String command, String arg) {
synchronized (mStateMachines) {
final HeadsetStateMachine stateMachine = mStateMachines.get(device);
if (stateMachine == null) {
@@ -2396,9 +2090,10 @@ public class HeadsetService extends ProfileService {
// Do it here because some controllers cannot handle SCO and CIS
// co-existence see {@link LeAudioService#setInactiveForHfpHandover}
LeAudioService leAudioService = mFactory.getLeAudioService();
- boolean isLeAudioConnectedDeviceNotActive = leAudioService != null
- && !leAudioService.getConnectedDevices().isEmpty()
- && leAudioService.getActiveDevices().get(0) == null;
+ boolean isLeAudioConnectedDeviceNotActive =
+ leAudioService != null
+ && !leAudioService.getConnectedDevices().isEmpty()
+ && leAudioService.getActiveDevices().get(0) == null;
// usually controller limitation cause CONNECTING -> DISCONNECTED, so only
// resume LE audio active device if it is HFP audio only and SCO disconnected
if (fromState != BluetoothHeadset.STATE_AUDIO_CONNECTING
diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetServiceBinder.java b/android/app/src/com/android/bluetooth/hfp/HeadsetServiceBinder.java
new file mode 100644
index 0000000000..d93ad5dc5f
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/hfp/HeadsetServiceBinder.java
@@ -0,0 +1,319 @@
+/*
+ * 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.bluetooth.hfp;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.Manifest.permission.MODIFY_PHONE_STATE;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.RequiresPermission;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothStatusCodes;
+import android.bluetooth.IBluetoothHeadset;
+import android.content.AttributionSource;
+
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+
+import java.util.Collections;
+import java.util.List;
+
+class HeadsetServiceBinder extends IBluetoothHeadset.Stub implements IProfileServiceBinder {
+ private static final String TAG = HeadsetServiceBinder.class.getSimpleName();
+
+ private HeadsetService mService;
+
+ HeadsetServiceBinder(HeadsetService svc) {
+ mService = svc;
+ }
+
+ @Override
+ public void cleanup() {
+ mService = null;
+ }
+
+ @RequiresPermission(BLUETOOTH_CONNECT)
+ private HeadsetService getService(AttributionSource source) {
+ HeadsetService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
+ || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
+ return null;
+ }
+ return service;
+ }
+
+ @Override
+ public boolean connect(BluetoothDevice device, AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
+ return service.connect(device);
+ }
+
+ @Override
+ public boolean disconnect(BluetoothDevice device, AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.disconnect(device);
+ }
+
+ @Override
+ public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getConnectedDevices();
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ int[] states, AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getDevicesMatchingConnectionStates(states);
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice device, AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return STATE_DISCONNECTED;
+ }
+ return service.getConnectionState(device);
+ }
+
+ @Override
+ public boolean setConnectionPolicy(
+ BluetoothDevice device, int connectionPolicy, AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.setConnectionPolicy(device, connectionPolicy);
+ }
+
+ @Override
+ public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return CONNECTION_POLICY_UNKNOWN;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getConnectionPolicy(device);
+ }
+
+ @Override
+ public boolean isNoiseReductionSupported(BluetoothDevice device, AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.isNoiseReductionSupported(device);
+ }
+
+ @Override
+ public boolean isVoiceRecognitionSupported(BluetoothDevice device, AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.isVoiceRecognitionSupported(device);
+ }
+
+ @Override
+ public boolean startVoiceRecognition(BluetoothDevice device, AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ requireNonNull(device);
+ return service.startVoiceRecognition(device);
+ }
+
+ @Override
+ public boolean stopVoiceRecognition(BluetoothDevice device, AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.stopVoiceRecognition(device);
+ }
+
+ @Override
+ public boolean isAudioConnected(BluetoothDevice device, AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.isAudioConnected(device);
+ }
+
+ @Override
+ public int getAudioState(BluetoothDevice device, AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return BluetoothHeadset.STATE_AUDIO_DISCONNECTED;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getAudioState(device);
+ }
+
+ @Override
+ public int connectAudio(AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.connectAudio();
+ }
+
+ @Override
+ public int disconnectAudio(AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.disconnectAudio();
+ }
+
+ @Override
+ public void setAudioRouteAllowed(boolean allowed, AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.setAudioRouteAllowed(allowed);
+ }
+
+ @Override
+ public boolean getAudioRouteAllowed(AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getAudioRouteAllowed();
+ }
+
+ @Override
+ public void setForceScoAudio(boolean forced, AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return;
+ }
+ service.setForceScoAudio(forced);
+ }
+
+ @Override
+ public boolean startScoUsingVirtualVoiceCall(AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+
+ return service.startScoUsingVirtualVoiceCall();
+ }
+
+ @Override
+ public boolean stopScoUsingVirtualVoiceCall(AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+
+ return service.stopScoUsingVirtualVoiceCall();
+ }
+
+ @Override
+ public boolean sendVendorSpecificResultCode(
+ BluetoothDevice device, String command, String arg, AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.sendVendorSpecificResultCode(device, command, arg);
+ }
+
+ @Override
+ public boolean setActiveDevice(BluetoothDevice device, AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);
+ return service.setActiveDevice(device);
+ }
+
+ @Override
+ public BluetoothDevice getActiveDevice(AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return null;
+ }
+ return service.getActiveDevice();
+ }
+
+ @Override
+ public boolean isInbandRingingEnabled(AttributionSource source) {
+ HeadsetService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.isInbandRingingEnabled();
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java b/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
index 4e8e14a547..6ea741af32 100644
--- a/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
+++ b/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
@@ -1044,7 +1044,8 @@ class HeadsetStateMachine extends StateMachine {
+ " is not currentDevice");
break;
}
- if (!mNativeInterface.startVoiceRecognition(mDevice)) {
+ if (!mNativeInterface.startVoiceRecognition(
+ mDevice, /* sendResult */ true)) {
stateLogW("Failed to start voice recognition");
break;
}
@@ -1122,6 +1123,9 @@ class HeadsetStateMachine extends StateMachine {
? HeadsetHalConstants.AT_RESPONSE_OK
: HeadsetHalConstants.AT_RESPONSE_ERROR,
0);
+ if (Utils.isScoManagedByAudioEnabled()) {
+ mNativeInterface.startVoiceRecognition(mDevice, /* sendResult */ false);
+ }
break;
}
case DIALING_OUT_RESULT:
diff --git a/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java b/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java
index 9c0e416168..7d3a5ff43f 100644
--- a/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java
+++ b/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java
@@ -16,11 +16,8 @@
package com.android.bluetooth.hfpclient;
-import static android.Manifest.permission.BLUETOOTH_CONNECT;
-import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
import static android.bluetooth.BluetoothProfile.STATE_CONNECTING;
import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
@@ -28,15 +25,11 @@ import static android.content.pm.PackageManager.FEATURE_WATCH;
import static java.util.Objects.requireNonNull;
-import android.annotation.RequiresPermission;
import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHeadsetClient;
import android.bluetooth.BluetoothHeadsetClientCall;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothSinkAudioPolicy;
import android.bluetooth.BluetoothStatusCodes;
-import android.bluetooth.IBluetoothHeadsetClient;
-import android.content.AttributionSource;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -58,7 +51,6 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -145,7 +137,7 @@ public class HeadsetClientService extends ProfileService {
@Override
public IProfileServiceBinder initBinder() {
- return new BluetoothHeadsetClientBinder(this);
+ return new HeadsetClientServiceBinder(this);
}
@Override
@@ -290,340 +282,6 @@ public class HeadsetClientService extends ProfileService {
call.isInBandRing());
}
- /** Handlers for incoming service calls */
- @VisibleForTesting
- static class BluetoothHeadsetClientBinder extends IBluetoothHeadsetClient.Stub
- implements IProfileServiceBinder {
- private HeadsetClientService mService;
-
- BluetoothHeadsetClientBinder(HeadsetClientService svc) {
- mService = svc;
- }
-
- @Override
- public void cleanup() {
- mService = null;
- }
-
- @RequiresPermission(BLUETOOTH_CONNECT)
- private HeadsetClientService getService(AttributionSource source) {
- // Cache mService because it can change while getService is called
- HeadsetClientService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
-
- return service;
- }
-
- @Override
- public boolean connect(BluetoothDevice device, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.connect(device);
- }
-
- @Override
- public boolean disconnect(BluetoothDevice device, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.disconnect(device);
- }
-
- @Override
- public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- service.enforceCallingPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getConnectedDevices();
- }
-
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(
- int[] states, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- service.enforceCallingPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getDevicesMatchingConnectionStates(states);
- }
-
- @Override
- public int getConnectionState(BluetoothDevice device, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return STATE_DISCONNECTED;
- }
-
- service.enforceCallingPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getConnectionState(device);
- }
-
- @Override
- public boolean setConnectionPolicy(
- BluetoothDevice device, int connectionPolicy, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.setConnectionPolicy(device, connectionPolicy);
- }
-
- @Override
- public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return CONNECTION_POLICY_UNKNOWN;
- }
-
- service.enforceCallingPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getConnectionPolicy(device);
- }
-
- @Override
- public boolean startVoiceRecognition(BluetoothDevice device, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.startVoiceRecognition(device);
- }
-
- @Override
- public boolean stopVoiceRecognition(BluetoothDevice device, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.stopVoiceRecognition(device);
- }
-
- @Override
- public int getAudioState(BluetoothDevice device, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED;
- }
-
- return service.getAudioState(device);
- }
-
- @Override
- public void setAudioRouteAllowed(
- BluetoothDevice device, boolean allowed, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- Log.w(TAG, "Service handle is null for setAudioRouteAllowed!");
- return;
- }
-
- service.setAudioRouteAllowed(device, allowed);
- }
-
- @Override
- public boolean getAudioRouteAllowed(BluetoothDevice device, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- Log.w(TAG, "Service handle is null for getAudioRouteAllowed!");
- return false;
- }
-
- return service.getAudioRouteAllowed(device);
- }
-
- @Override
- public boolean connectAudio(BluetoothDevice device, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.connectAudio(device);
- }
-
- @Override
- public boolean disconnectAudio(BluetoothDevice device, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.disconnectAudio(device);
- }
-
- @Override
- public boolean acceptCall(BluetoothDevice device, int flag, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.acceptCall(device, flag);
- }
-
- @Override
- public boolean rejectCall(BluetoothDevice device, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.rejectCall(device);
- }
-
- @Override
- public boolean holdCall(BluetoothDevice device, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.holdCall(device);
- }
-
- @Override
- public boolean terminateCall(
- BluetoothDevice device, BluetoothHeadsetClientCall call, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- Log.w(TAG, "service is null");
- return false;
- }
-
- return service.terminateCall(device, call != null ? call.getUUID() : null);
- }
-
- @Override
- public boolean explicitCallTransfer(BluetoothDevice device, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.explicitCallTransfer(device);
- }
-
- @Override
- public boolean enterPrivateMode(
- BluetoothDevice device, int index, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.enterPrivateMode(device, index);
- }
-
- @Override
- public BluetoothHeadsetClientCall dial(
- BluetoothDevice device, String number, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return null;
- }
-
- return toLegacyCall(service.dial(device, number));
- }
-
- @Override
- public List<BluetoothHeadsetClientCall> getCurrentCalls(
- BluetoothDevice device, AttributionSource source) {
- HeadsetClientService service = getService(source);
- List<BluetoothHeadsetClientCall> currentCalls = new ArrayList<>();
- if (service == null) {
- return currentCalls;
- }
-
- List<HfpClientCall> calls = service.getCurrentCalls(device);
- if (calls != null) {
- for (HfpClientCall call : calls) {
- currentCalls.add(toLegacyCall(call));
- }
- }
- return currentCalls;
- }
-
- @Override
- public boolean sendDTMF(BluetoothDevice device, byte code, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.sendDTMF(device, code);
- }
-
- @Override
- public boolean getLastVoiceTagNumber(BluetoothDevice device, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.getLastVoiceTagNumber(device);
- }
-
- @Override
- public Bundle getCurrentAgEvents(BluetoothDevice device, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return null;
- }
-
- service.enforceCallingPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getCurrentAgEvents(device);
- }
-
- @Override
- public boolean sendVendorAtCommand(
- BluetoothDevice device, int vendorId, String atCommand, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.sendVendorAtCommand(device, vendorId, atCommand);
- }
-
- @Override
- public Bundle getCurrentAgFeatures(BluetoothDevice device, AttributionSource source) {
- HeadsetClientService service = getService(source);
- if (service == null) {
- return null;
- }
-
- return service.getCurrentAgFeaturesBundle(device);
- }
- }
-
// API methods
public static synchronized HeadsetClientService getHeadsetClientService() {
if (sHeadsetClientService == null) {
diff --git a/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientServiceBinder.java b/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientServiceBinder.java
new file mode 100644
index 0000000000..3232fccd4f
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientServiceBinder.java
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.hfpclient;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+
+import android.annotation.RequiresPermission;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadsetClient;
+import android.bluetooth.BluetoothHeadsetClientCall;
+import android.bluetooth.IBluetoothHeadsetClient;
+import android.content.AttributionSource;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/** Handlers for incoming service calls */
+class HeadsetClientServiceBinder extends IBluetoothHeadsetClient.Stub
+ implements IProfileServiceBinder {
+ private static final String TAG = HeadsetClientServiceBinder.class.getSimpleName();
+
+ private HeadsetClientService mService;
+
+ HeadsetClientServiceBinder(HeadsetClientService svc) {
+ mService = svc;
+ }
+
+ @Override
+ public void cleanup() {
+ mService = null;
+ }
+
+ @RequiresPermission(BLUETOOTH_CONNECT)
+ private HeadsetClientService getService(AttributionSource source) {
+ HeadsetClientService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
+ || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
+ return null;
+ }
+
+ return service;
+ }
+
+ @Override
+ public boolean connect(BluetoothDevice device, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.connect(device);
+ }
+
+ @Override
+ public boolean disconnect(BluetoothDevice device, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.disconnect(device);
+ }
+
+ @Override
+ public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+
+ service.enforceCallingPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getConnectedDevices();
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ int[] states, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+
+ service.enforceCallingPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getDevicesMatchingConnectionStates(states);
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice device, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return STATE_DISCONNECTED;
+ }
+
+ service.enforceCallingPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getConnectionState(device);
+ }
+
+ @Override
+ public boolean setConnectionPolicy(
+ BluetoothDevice device, int connectionPolicy, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.setConnectionPolicy(device, connectionPolicy);
+ }
+
+ @Override
+ public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return CONNECTION_POLICY_UNKNOWN;
+ }
+
+ service.enforceCallingPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getConnectionPolicy(device);
+ }
+
+ @Override
+ public boolean startVoiceRecognition(BluetoothDevice device, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.startVoiceRecognition(device);
+ }
+
+ @Override
+ public boolean stopVoiceRecognition(BluetoothDevice device, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.stopVoiceRecognition(device);
+ }
+
+ @Override
+ public int getAudioState(BluetoothDevice device, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED;
+ }
+ return service.getAudioState(device);
+ }
+
+ @Override
+ public void setAudioRouteAllowed(
+ BluetoothDevice device, boolean allowed, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ Log.w(TAG, "Service handle is null for setAudioRouteAllowed!");
+ return;
+ }
+ service.setAudioRouteAllowed(device, allowed);
+ }
+
+ @Override
+ public boolean getAudioRouteAllowed(BluetoothDevice device, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ Log.w(TAG, "Service handle is null for getAudioRouteAllowed!");
+ return false;
+ }
+ return service.getAudioRouteAllowed(device);
+ }
+
+ @Override
+ public boolean connectAudio(BluetoothDevice device, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.connectAudio(device);
+ }
+
+ @Override
+ public boolean disconnectAudio(BluetoothDevice device, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.disconnectAudio(device);
+ }
+
+ @Override
+ public boolean acceptCall(BluetoothDevice device, int flag, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.acceptCall(device, flag);
+ }
+
+ @Override
+ public boolean rejectCall(BluetoothDevice device, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.rejectCall(device);
+ }
+
+ @Override
+ public boolean holdCall(BluetoothDevice device, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.holdCall(device);
+ }
+
+ @Override
+ public boolean terminateCall(
+ BluetoothDevice device, BluetoothHeadsetClientCall call, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ Log.w(TAG, "service is null");
+ return false;
+ }
+ return service.terminateCall(device, call != null ? call.getUUID() : null);
+ }
+
+ @Override
+ public boolean explicitCallTransfer(BluetoothDevice device, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.explicitCallTransfer(device);
+ }
+
+ @Override
+ public boolean enterPrivateMode(BluetoothDevice device, int index, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.enterPrivateMode(device, index);
+ }
+
+ @Override
+ public BluetoothHeadsetClientCall dial(
+ BluetoothDevice device, String number, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return null;
+ }
+ return HeadsetClientService.toLegacyCall(service.dial(device, number));
+ }
+
+ @Override
+ public List<BluetoothHeadsetClientCall> getCurrentCalls(
+ BluetoothDevice device, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ List<BluetoothHeadsetClientCall> currentCalls = new ArrayList<>();
+ if (service == null) {
+ return currentCalls;
+ }
+
+ List<HfpClientCall> calls = service.getCurrentCalls(device);
+ if (calls != null) {
+ for (HfpClientCall call : calls) {
+ currentCalls.add(HeadsetClientService.toLegacyCall(call));
+ }
+ }
+ return currentCalls;
+ }
+
+ @Override
+ public boolean sendDTMF(BluetoothDevice device, byte code, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.sendDTMF(device, code);
+ }
+
+ @Override
+ public boolean getLastVoiceTagNumber(BluetoothDevice device, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.getLastVoiceTagNumber(device);
+ }
+
+ @Override
+ public Bundle getCurrentAgEvents(BluetoothDevice device, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return null;
+ }
+
+ service.enforceCallingPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getCurrentAgEvents(device);
+ }
+
+ @Override
+ public boolean sendVendorAtCommand(
+ BluetoothDevice device, int vendorId, String atCommand, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.sendVendorAtCommand(device, vendorId, atCommand);
+ }
+
+ @Override
+ public Bundle getCurrentAgFeatures(BluetoothDevice device, AttributionSource source) {
+ HeadsetClientService service = getService(source);
+ if (service == null) {
+ return null;
+ }
+ return service.getCurrentAgFeaturesBundle(device);
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/hfpclient/NativeInterface.java b/android/app/src/com/android/bluetooth/hfpclient/NativeInterface.java
index fbb68747fe..bcbb49fba6 100644
--- a/android/app/src/com/android/bluetooth/hfpclient/NativeInterface.java
+++ b/android/app/src/com/android/bluetooth/hfpclient/NativeInterface.java
@@ -27,7 +27,6 @@ import android.util.Log;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AdapterService;
-import com.android.bluetooth.flags.Flags;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -334,12 +333,8 @@ public class NativeInterface {
return mAdapterService.getDeviceFromByte(address);
}
- private byte[] getByteAddress(BluetoothDevice device) {
- if (Flags.identityAddressNullIfNotKnown()) {
- return Utils.getByteBrEdrAddress(device);
- } else {
- return mAdapterService.getByteIdentityAddress(device);
- }
+ private static byte[] getByteAddress(BluetoothDevice device) {
+ return Utils.getByteBrEdrAddress(device);
}
// Callbacks from the native back into the java framework. All callbacks are routed via the
diff --git a/android/app/src/com/android/bluetooth/hfpclient/OWNERS b/android/app/src/com/android/bluetooth/hfpclient/OWNERS
deleted file mode 100644
index ecd59038a1..0000000000
--- a/android/app/src/com/android/bluetooth/hfpclient/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_automotive
diff --git a/android/app/src/com/android/bluetooth/hid/HidDeviceNativeInterface.java b/android/app/src/com/android/bluetooth/hid/HidDeviceNativeInterface.java
index 2ca9078103..dc269b7abf 100644
--- a/android/app/src/com/android/bluetooth/hid/HidDeviceNativeInterface.java
+++ b/android/app/src/com/android/bluetooth/hid/HidDeviceNativeInterface.java
@@ -29,7 +29,6 @@ import android.util.Log;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AdapterService;
-import com.android.bluetooth.flags.Flags;
import com.android.internal.annotations.VisibleForTesting;
/** HID Device Native Interface to/from JNI. */
@@ -123,7 +122,7 @@ public class HidDeviceNativeInterface {
* @return the result of the native call
*/
public boolean connect(BluetoothDevice device) {
- return connectNative(getByteAddress(device));
+ return connectNative(Utils.getByteBrEdrAddress(device));
}
/**
@@ -243,14 +242,6 @@ public class HidDeviceNativeInterface {
return mAdapterService.getDeviceFromByte(address);
}
- private byte[] getByteAddress(BluetoothDevice device) {
- if (Flags.identityAddressNullIfNotKnown()) {
- return Utils.getByteBrEdrAddress(device);
- } else {
- return mAdapterService.getByteIdentityAddress(device);
- }
- }
-
private native void initNative();
private native void cleanupNative();
diff --git a/android/app/src/com/android/bluetooth/hid/HidDeviceService.java b/android/app/src/com/android/bluetooth/hid/HidDeviceService.java
index 2c2f11940e..d3d84d9630 100644
--- a/android/app/src/com/android/bluetooth/hid/HidDeviceService.java
+++ b/android/app/src/com/android/bluetooth/hid/HidDeviceService.java
@@ -34,9 +34,7 @@ import android.bluetooth.BluetoothHidDevice;
import android.bluetooth.BluetoothHidDeviceAppQosSettings;
import android.bluetooth.BluetoothHidDeviceAppSdpSettings;
import android.bluetooth.BluetoothProfile;
-import android.bluetooth.IBluetoothHidDevice;
import android.bluetooth.IBluetoothHidDeviceCallback;
-import android.content.AttributionSource;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
@@ -50,15 +48,12 @@ import android.util.Log;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AdapterService;
-import com.android.bluetooth.btservice.MetricsLogger;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.btservice.storage.DatabaseManager;
import com.android.internal.annotations.VisibleForTesting;
import java.nio.ByteBuffer;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.NoSuchElementException;
@@ -328,204 +323,9 @@ public class HidDeviceService extends ProfileService {
}
};
- @VisibleForTesting
- static class BluetoothHidDeviceBinder extends IBluetoothHidDevice.Stub
- implements IProfileServiceBinder {
-
- private static final String TAG = BluetoothHidDeviceBinder.class.getSimpleName();
-
- private HidDeviceService mService;
-
- BluetoothHidDeviceBinder(HidDeviceService service) {
- mService = service;
- }
-
- @Override
- public void cleanup() {
- mService = null;
- }
-
- @RequiresPermission(BLUETOOTH_CONNECT)
- private HidDeviceService getService(AttributionSource source) {
- // Cache mService because it can change while getService is called
- HidDeviceService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
- return service;
- }
-
- @Override
- public boolean registerApp(
- BluetoothHidDeviceAppSdpSettings sdp,
- BluetoothHidDeviceAppQosSettings inQos,
- BluetoothHidDeviceAppQosSettings outQos,
- IBluetoothHidDeviceCallback callback,
- AttributionSource source) {
- Log.d(TAG, "registerApp()");
-
- HidDeviceService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.registerApp(sdp, inQos, outQos, callback);
- }
-
- @Override
- public boolean unregisterApp(AttributionSource source) {
- Log.d(TAG, "unregisterApp()");
-
- HidDeviceService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.unregisterApp();
- }
-
- @Override
- public boolean sendReport(
- BluetoothDevice device, int id, byte[] data, AttributionSource source) {
- Log.d(TAG, "sendReport(): device=" + device + " id=" + id);
-
- HidDeviceService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.sendReport(device, id, data);
- }
-
- @Override
- public boolean replyReport(
- BluetoothDevice device, byte type, byte id, byte[] data, AttributionSource source) {
- Log.d(TAG, "replyReport(): device=" + device + " type=" + type + " id=" + id);
-
- HidDeviceService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.replyReport(device, type, id, data);
- }
-
- @Override
- public boolean unplug(BluetoothDevice device, AttributionSource source) {
- Log.d(TAG, "unplug(): device=" + device);
-
- HidDeviceService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.unplug(device);
- }
-
- @Override
- public boolean connect(BluetoothDevice device, AttributionSource source) {
- Log.d(TAG, "connect(): device=" + device);
-
- HidDeviceService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.connect(device);
- }
-
- @Override
- public boolean disconnect(BluetoothDevice device, AttributionSource source) {
- Log.d(TAG, "disconnect(): device=" + device);
-
- HidDeviceService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.disconnect(device);
- }
-
- @Override
- public boolean setConnectionPolicy(
- BluetoothDevice device, int connectionPolicy, AttributionSource source) {
- Log.d(
- TAG,
- "setConnectionPolicy():"
- + (" device=" + device)
- + (" connectionPolicy=" + connectionPolicy));
-
- HidDeviceService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.setConnectionPolicy(device, connectionPolicy);
- }
-
- @Override
- public boolean reportError(BluetoothDevice device, byte error, AttributionSource source) {
- Log.d(TAG, "reportError(): device=" + device + " error=" + error);
-
- HidDeviceService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.reportError(device, error);
- }
-
- @Override
- public int getConnectionState(BluetoothDevice device, AttributionSource source) {
- Log.d(TAG, "getConnectionState(): device=" + device);
-
- HidDeviceService service = getService(source);
- if (service == null) {
- return BluetoothHidDevice.STATE_DISCONNECTED;
- }
-
- return service.getConnectionState(device);
- }
-
- @Override
- public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
- Log.d(TAG, "getConnectedDevices()");
-
- return getDevicesMatchingConnectionStates(new int[] {STATE_CONNECTED}, source);
- }
-
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(
- int[] states, AttributionSource source) {
- Log.d(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states));
-
- HidDeviceService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- return service.getDevicesMatchingConnectionStates(states);
- }
-
- @Override
- public String getUserAppName(AttributionSource source) {
- HidDeviceService service = getService(source);
- if (service == null) {
- return "";
- }
- return service.getUserAppName();
- }
- }
-
@Override
protected IProfileServiceBinder initBinder() {
- return new BluetoothHidDeviceBinder(this);
+ return new HidDeviceServiceBinder(this);
}
private boolean checkDevice(BluetoothDevice device) {
diff --git a/android/app/src/com/android/bluetooth/hid/HidDeviceServiceBinder.java b/android/app/src/com/android/bluetooth/hid/HidDeviceServiceBinder.java
new file mode 100644
index 0000000000..0cd0e1d301
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/hid/HidDeviceServiceBinder.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.hid;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
+
+import android.annotation.RequiresPermission;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHidDevice;
+import android.bluetooth.BluetoothHidDeviceAppQosSettings;
+import android.bluetooth.BluetoothHidDeviceAppSdpSettings;
+import android.bluetooth.IBluetoothHidDevice;
+import android.bluetooth.IBluetoothHidDeviceCallback;
+import android.content.AttributionSource;
+import android.util.Log;
+
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+class HidDeviceServiceBinder extends IBluetoothHidDevice.Stub implements IProfileServiceBinder {
+ private static final String TAG = HidDeviceServiceBinder.class.getSimpleName();
+
+ private HidDeviceService mService;
+
+ HidDeviceServiceBinder(HidDeviceService service) {
+ mService = service;
+ }
+
+ @Override
+ public void cleanup() {
+ mService = null;
+ }
+
+ @RequiresPermission(BLUETOOTH_CONNECT)
+ private HidDeviceService getService(AttributionSource source) {
+ // Cache mService because it can change while getService is called
+ HidDeviceService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
+ || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
+ return null;
+ }
+ return service;
+ }
+
+ @Override
+ public boolean registerApp(
+ BluetoothHidDeviceAppSdpSettings sdp,
+ BluetoothHidDeviceAppQosSettings inQos,
+ BluetoothHidDeviceAppQosSettings outQos,
+ IBluetoothHidDeviceCallback callback,
+ AttributionSource source) {
+ Log.d(TAG, "registerApp()");
+
+ HidDeviceService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.registerApp(sdp, inQos, outQos, callback);
+ }
+
+ @Override
+ public boolean unregisterApp(AttributionSource source) {
+ Log.d(TAG, "unregisterApp()");
+
+ HidDeviceService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.unregisterApp();
+ }
+
+ @Override
+ public boolean sendReport(
+ BluetoothDevice device, int id, byte[] data, AttributionSource source) {
+ Log.d(TAG, "sendReport(): device=" + device + " id=" + id);
+
+ HidDeviceService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.sendReport(device, id, data);
+ }
+
+ @Override
+ public boolean replyReport(
+ BluetoothDevice device, byte type, byte id, byte[] data, AttributionSource source) {
+ Log.d(TAG, "replyReport(): device=" + device + " type=" + type + " id=" + id);
+
+ HidDeviceService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.replyReport(device, type, id, data);
+ }
+
+ @Override
+ public boolean unplug(BluetoothDevice device, AttributionSource source) {
+ Log.d(TAG, "unplug(): device=" + device);
+
+ HidDeviceService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.unplug(device);
+ }
+
+ @Override
+ public boolean connect(BluetoothDevice device, AttributionSource source) {
+ Log.d(TAG, "connect(): device=" + device);
+
+ HidDeviceService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.connect(device);
+ }
+
+ @Override
+ public boolean disconnect(BluetoothDevice device, AttributionSource source) {
+ Log.d(TAG, "disconnect(): device=" + device);
+
+ HidDeviceService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.disconnect(device);
+ }
+
+ @Override
+ public boolean setConnectionPolicy(
+ BluetoothDevice device, int connectionPolicy, AttributionSource source) {
+ Log.d(
+ TAG,
+ "setConnectionPolicy():"
+ + (" device=" + device)
+ + (" connectionPolicy=" + connectionPolicy));
+
+ HidDeviceService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.setConnectionPolicy(device, connectionPolicy);
+ }
+
+ @Override
+ public boolean reportError(BluetoothDevice device, byte error, AttributionSource source) {
+ Log.d(TAG, "reportError(): device=" + device + " error=" + error);
+
+ HidDeviceService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.reportError(device, error);
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice device, AttributionSource source) {
+ Log.d(TAG, "getConnectionState(): device=" + device);
+
+ HidDeviceService service = getService(source);
+ if (service == null) {
+ return BluetoothHidDevice.STATE_DISCONNECTED;
+ }
+ return service.getConnectionState(device);
+ }
+
+ @Override
+ public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
+ Log.d(TAG, "getConnectedDevices()");
+
+ return getDevicesMatchingConnectionStates(new int[] {STATE_CONNECTED}, source);
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ int[] states, AttributionSource source) {
+ Log.d(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states));
+
+ HidDeviceService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getDevicesMatchingConnectionStates(states);
+ }
+
+ @Override
+ public String getUserAppName(AttributionSource source) {
+ HidDeviceService service = getService(source);
+ if (service == null) {
+ return "";
+ }
+ return service.getUserAppName();
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/hid/HidHostService.java b/android/app/src/com/android/bluetooth/hid/HidHostService.java
index 3a29ed5b62..68c2be4a8b 100644
--- a/android/app/src/com/android/bluetooth/hid/HidHostService.java
+++ b/android/app/src/com/android/bluetooth/hid/HidHostService.java
@@ -17,7 +17,6 @@
package com.android.bluetooth.hid;
import static android.Manifest.permission.BLUETOOTH_CONNECT;
-import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
@@ -27,14 +26,11 @@ import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTING;
import static java.util.Objects.requireNonNull;
-import android.annotation.RequiresPermission;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHidHost;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothProtoEnums;
import android.bluetooth.BluetoothUuid;
-import android.bluetooth.IBluetoothHidHost;
-import android.content.AttributionSource;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
@@ -145,7 +141,7 @@ public class HidHostService extends ProfileService {
@Override
public IProfileServiceBinder initBinder() {
- return new BluetoothHidHostBinder(this);
+ return new HidHostServiceBinder(this);
}
@Override
@@ -166,14 +162,6 @@ public class HidHostService extends ProfileService {
setHidHostService(null);
}
- private byte[] getIdentityAddress(BluetoothDevice device) {
- if (Flags.identityAddressNullIfNotKnown()) {
- return Utils.getByteBrEdrAddress(mAdapterService, device);
- } else {
- return mAdapterService.getByteIdentityAddress(device);
- }
- }
-
private byte[] getByteAddress(BluetoothDevice device, int transport) {
final ParcelUuid[] uuids = mAdapterService.getRemoteUuids(device);
@@ -181,14 +169,14 @@ public class HidHostService extends ProfileService {
// Use pseudo address when HOGP is to be used
return Utils.getByteAddress(device);
} else if (transport == BluetoothDevice.TRANSPORT_BREDR) {
- // Use identity address if HID is to be used
- return getIdentityAddress(device);
+ // Use BR/EDR address if HID is to be used
+ return Utils.getByteBrEdrAddress(mAdapterService, device);
} else { // BluetoothDevice.TRANSPORT_AUTO
boolean hidSupported = Utils.arrayContains(uuids, BluetoothUuid.HID);
// Prefer HID over HOGP
if (hidSupported) {
- // Use identity address if HID is available
- return getIdentityAddress(device);
+ // Use BR/EDR address if HID is available
+ return Utils.getByteBrEdrAddress(mAdapterService, device);
} else {
// Otherwise use pseudo address
return Utils.getByteAddress(device);
@@ -713,207 +701,6 @@ public class HidHostService extends ProfileService {
return true;
}
- @VisibleForTesting
- static class BluetoothHidHostBinder extends IBluetoothHidHost.Stub
- implements IProfileServiceBinder {
- private HidHostService mService;
-
- BluetoothHidHostBinder(HidHostService svc) {
- mService = svc;
- }
-
- @Override
- public void cleanup() {
- mService = null;
- }
-
- @RequiresPermission(BLUETOOTH_CONNECT)
- private HidHostService getService(AttributionSource source) {
- // Cache mService because it can change while getService is called
- HidHostService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
-
- return service;
- }
-
- @Override
- public boolean connect(BluetoothDevice device, AttributionSource source) {
- HidHostService service = getService(source);
- if (service == null) {
- return false;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.connect(device);
- }
-
- @Override
- public boolean disconnect(BluetoothDevice device, AttributionSource source) {
- HidHostService service = getService(source);
- if (service == null) {
- return false;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.disconnect(device);
- }
-
- @Override
- public int getConnectionState(BluetoothDevice device, AttributionSource source) {
- HidHostService service = getService(source);
- if (service == null) {
- return STATE_DISCONNECTED;
- }
- return service.getConnectionState(device);
- }
-
- @Override
- public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
- return getDevicesMatchingConnectionStates(new int[] {STATE_CONNECTED}, source);
- }
-
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(
- int[] states, AttributionSource source) {
- HidHostService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
- return service.getDevicesMatchingConnectionStates(states);
- }
-
- @Override
- public boolean setConnectionPolicy(
- BluetoothDevice device, int connectionPolicy, AttributionSource source) {
- HidHostService service = getService(source);
- if (service == null) {
- return false;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.setConnectionPolicy(device, connectionPolicy);
- }
-
- @Override
- public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
- HidHostService service = getService(source);
- if (service == null) {
- return CONNECTION_POLICY_UNKNOWN;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getConnectionPolicy(device);
- }
-
- @Override
- public boolean setPreferredTransport(
- BluetoothDevice device, int transport, AttributionSource source) {
- HidHostService service = getService(source);
- if (service == null) {
- return false;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.setPreferredTransport(device, transport);
- }
-
- @Override
- public int getPreferredTransport(BluetoothDevice device, AttributionSource source) {
- HidHostService service = getService(source);
- if (service == null) {
- return BluetoothDevice.TRANSPORT_AUTO;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getPreferredTransport(device);
- }
-
- /* The following APIs regarding test app for compliance */
- @Override
- public boolean getProtocolMode(BluetoothDevice device, AttributionSource source) {
- HidHostService service = getService(source);
- if (service == null) {
- return false;
- }
- return service.getProtocolMode(device);
- }
-
- @Override
- public boolean virtualUnplug(BluetoothDevice device, AttributionSource source) {
- HidHostService service = getService(source);
- if (service == null) {
- return false;
- }
- return service.virtualUnplug(device);
- }
-
- @Override
- public boolean setProtocolMode(
- BluetoothDevice device, int protocolMode, AttributionSource source) {
- HidHostService service = getService(source);
- if (service == null) {
- return false;
- }
- return service.setProtocolMode(device, protocolMode);
- }
-
- @Override
- public boolean getReport(
- BluetoothDevice device,
- byte reportType,
- byte reportId,
- int bufferSize,
- AttributionSource source) {
- HidHostService service = getService(source);
- if (service == null) {
- return false;
- }
- return service.getReport(device, reportType, reportId, bufferSize);
- }
-
- @Override
- public boolean setReport(
- BluetoothDevice device, byte reportType, String report, AttributionSource source) {
- HidHostService service = getService(source);
- if (service == null) {
- return false;
- }
- return service.setReport(device, reportType, report);
- }
-
- @Override
- public boolean sendData(BluetoothDevice device, String report, AttributionSource source) {
- HidHostService service = getService(source);
- if (service == null) {
- return false;
- }
- return service.sendData(device, report);
- }
-
- @Override
- public boolean setIdleTime(
- BluetoothDevice device, byte idleTime, AttributionSource source) {
- HidHostService service = getService(source);
- if (service == null) {
- return false;
- }
- return service.setIdleTime(device, idleTime);
- }
-
- @Override
- public boolean getIdleTime(BluetoothDevice device, AttributionSource source) {
- HidHostService service = getService(source);
- if (service == null) {
- return false;
- }
- return service.getIdleTime(device);
- }
- }
- ;
-
// APIs
/**
@@ -982,7 +769,6 @@ public class HidHostService extends ProfileService {
return STATE_DISCONNECTED;
}
- @VisibleForTesting
List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
Log.d(TAG, "getDevicesMatchingConnectionStates()");
return mInputDevices.entrySet().stream()
@@ -1073,7 +859,6 @@ public class HidHostService extends ProfileService {
/**
* @see BluetoothHidHost#getPreferredTransport
*/
- @VisibleForTesting
int getPreferredTransport(BluetoothDevice device) {
Log.d(TAG, "getPreferredTransport: device=" + device);
@@ -1082,7 +867,6 @@ public class HidHostService extends ProfileService {
}
/* The following APIs regarding test app for compliance */
- @VisibleForTesting
boolean getProtocolMode(BluetoothDevice device) {
Log.d(TAG, "getProtocolMode: device=" + device);
int state = this.getConnectionState(device);
@@ -1094,7 +878,6 @@ public class HidHostService extends ProfileService {
return true;
}
- @VisibleForTesting
boolean virtualUnplug(BluetoothDevice device) {
Log.d(TAG, "virtualUnplug: device=" + device);
int state = this.getConnectionState(device);
@@ -1106,7 +889,6 @@ public class HidHostService extends ProfileService {
return true;
}
- @VisibleForTesting
boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
Log.d(TAG, "setProtocolMode: device=" + device);
int state = this.getConnectionState(device);
@@ -1120,7 +902,6 @@ public class HidHostService extends ProfileService {
return true;
}
- @VisibleForTesting
boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) {
Log.d(TAG, "getReport: device=" + device);
int state = this.getConnectionState(device);
@@ -1138,7 +919,6 @@ public class HidHostService extends ProfileService {
return true;
}
- @VisibleForTesting
boolean setReport(BluetoothDevice device, byte reportType, String report) {
Log.d(TAG, "setReport: device=" + device);
int state = this.getConnectionState(device);
@@ -1155,7 +935,6 @@ public class HidHostService extends ProfileService {
return true;
}
- @VisibleForTesting
boolean sendData(BluetoothDevice device, String report) {
Log.d(TAG, "sendData: device=" + device);
int state = this.getConnectionState(device);
@@ -1393,8 +1172,9 @@ public class HidHostService extends ProfileService {
// Allow this connection only if the device is bonded. Any attempt to connect
// while bonding would potentially lead to an unauthorized connection.
if (bondState != BluetoothDevice.BOND_BONDED) {
- Log.w(TAG, "okToConnect: return false, device=" + device + " bondState="
- + bondState);
+ Log.w(
+ TAG,
+ "okToConnect: return false, device=" + device + " bondState=" + bondState);
return false;
}
}
diff --git a/android/app/src/com/android/bluetooth/hid/HidHostServiceBinder.java b/android/app/src/com/android/bluetooth/hid/HidHostServiceBinder.java
new file mode 100644
index 0000000000..3295c83f01
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/hid/HidHostServiceBinder.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.hid;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
+import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+
+import android.annotation.RequiresPermission;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.IBluetoothHidHost;
+import android.content.AttributionSource;
+
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+
+import java.util.Collections;
+import java.util.List;
+
+class HidHostServiceBinder extends IBluetoothHidHost.Stub implements IProfileServiceBinder {
+ private static final String TAG = HidHostServiceBinder.class.getSimpleName();
+
+ private HidHostService mService;
+
+ HidHostServiceBinder(HidHostService svc) {
+ mService = svc;
+ }
+
+ @Override
+ public void cleanup() {
+ mService = null;
+ }
+
+ @RequiresPermission(BLUETOOTH_CONNECT)
+ private HidHostService getService(AttributionSource source) {
+ HidHostService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
+ || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
+ return null;
+ }
+
+ return service;
+ }
+
+ @Override
+ public boolean connect(BluetoothDevice device, AttributionSource source) {
+ HidHostService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.connect(device);
+ }
+
+ @Override
+ public boolean disconnect(BluetoothDevice device, AttributionSource source) {
+ HidHostService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.disconnect(device);
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice device, AttributionSource source) {
+ HidHostService service = getService(source);
+ if (service == null) {
+ return STATE_DISCONNECTED;
+ }
+ return service.getConnectionState(device);
+ }
+
+ @Override
+ public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
+ return getDevicesMatchingConnectionStates(new int[] {STATE_CONNECTED}, source);
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ int[] states, AttributionSource source) {
+ HidHostService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getDevicesMatchingConnectionStates(states);
+ }
+
+ @Override
+ public boolean setConnectionPolicy(
+ BluetoothDevice device, int connectionPolicy, AttributionSource source) {
+ HidHostService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.setConnectionPolicy(device, connectionPolicy);
+ }
+
+ @Override
+ public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
+ HidHostService service = getService(source);
+ if (service == null) {
+ return CONNECTION_POLICY_UNKNOWN;
+ }
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getConnectionPolicy(device);
+ }
+
+ @Override
+ public boolean setPreferredTransport(
+ BluetoothDevice device, int transport, AttributionSource source) {
+ HidHostService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.setPreferredTransport(device, transport);
+ }
+
+ @Override
+ public int getPreferredTransport(BluetoothDevice device, AttributionSource source) {
+ HidHostService service = getService(source);
+ if (service == null) {
+ return BluetoothDevice.TRANSPORT_AUTO;
+ }
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getPreferredTransport(device);
+ }
+
+ /* The following APIs regarding test app for compliance */
+ @Override
+ public boolean getProtocolMode(BluetoothDevice device, AttributionSource source) {
+ HidHostService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.getProtocolMode(device);
+ }
+
+ @Override
+ public boolean virtualUnplug(BluetoothDevice device, AttributionSource source) {
+ HidHostService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.virtualUnplug(device);
+ }
+
+ @Override
+ public boolean setProtocolMode(
+ BluetoothDevice device, int protocolMode, AttributionSource source) {
+ HidHostService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.setProtocolMode(device, protocolMode);
+ }
+
+ @Override
+ public boolean getReport(
+ BluetoothDevice device,
+ byte reportType,
+ byte reportId,
+ int bufferSize,
+ AttributionSource source) {
+ HidHostService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.getReport(device, reportType, reportId, bufferSize);
+ }
+
+ @Override
+ public boolean setReport(
+ BluetoothDevice device, byte reportType, String report, AttributionSource source) {
+ HidHostService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.setReport(device, reportType, report);
+ }
+
+ @Override
+ public boolean sendData(BluetoothDevice device, String report, AttributionSource source) {
+ HidHostService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.sendData(device, report);
+ }
+
+ @Override
+ public boolean setIdleTime(BluetoothDevice device, byte idleTime, AttributionSource source) {
+ HidHostService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.setIdleTime(device, idleTime);
+ }
+
+ @Override
+ public boolean getIdleTime(BluetoothDevice device, AttributionSource source) {
+ HidHostService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.getIdleTime(device);
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java
index cebf4270e5..4f0d215e5b 100644
--- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java
+++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java
@@ -27,6 +27,7 @@ import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
import static android.bluetooth.IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID;
import static com.android.bluetooth.bass_client.BassConstants.INVALID_BROADCAST_ID;
+import static com.android.bluetooth.flags.Flags.doNotHardcodeTmapRoleMask;
import static com.android.bluetooth.flags.Flags.leaudioBigDependsOnAudioState;
import static com.android.bluetooth.flags.Flags.leaudioBroadcastApiManagePrimaryGroup;
import static com.android.bluetooth.flags.Flags.leaudioMonitorUnicastSourceWhenManagedByBroadcastDelegator;
@@ -35,7 +36,6 @@ import static com.android.modules.utils.build.SdkLevel.isAtLeastU;
import static java.util.Objects.requireNonNull;
-import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.bluetooth.BluetoothAdapter;
@@ -60,7 +60,6 @@ import android.bluetooth.le.IScannerCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
-import android.content.AttributionSource;
import android.content.Context;
import android.content.Intent;
import android.media.AudioDeviceCallback;
@@ -261,24 +260,49 @@ public class LeAudioService extends ProfileService {
mStateMachinesThread.start();
// Initialize Broadcast native interface
- if ((mAdapterService.getSupportedProfilesBitMask()
- & (1 << BluetoothProfile.LE_AUDIO_BROADCAST))
- != 0) {
- Log.i(TAG, "Init Le Audio broadcaster");
- LeAudioBroadcasterNativeInterface broadcastNativeInterface =
- requireNonNull(LeAudioBroadcasterNativeInterface.getInstance());
- broadcastNativeInterface.init();
- mLeAudioBroadcasterNativeInterface = Optional.of(broadcastNativeInterface);
- mTmapRoleMask =
- LeAudioTmapGattServer.TMAP_ROLE_FLAG_CG
- | LeAudioTmapGattServer.TMAP_ROLE_FLAG_UMS
- | LeAudioTmapGattServer.TMAP_ROLE_FLAG_BMS;
+ if (doNotHardcodeTmapRoleMask()) {
+ int mask = 0;
+ if (isProfileSupported(BluetoothProfile.LE_CALL_CONTROL)) {
+ // Table 3.5 of TMAP v1.0: CCP Server is mandatory for the TMAP CG role.
+ mask |= LeAudioTmapGattServer.TMAP_ROLE_FLAG_CG;
+ }
+ if (isProfileSupported(BluetoothProfile.MCP_SERVER)) {
+ // Table 3.5 of TMAP v1.0: MCP Server is mandatory for the TMAP UMS role.
+ mask |= LeAudioTmapGattServer.TMAP_ROLE_FLAG_UMS;
+ }
+ if (isProfileSupported(BluetoothProfile.LE_AUDIO_BROADCAST)) {
+ Log.i(TAG, "Init Le Audio broadcaster");
+ LeAudioBroadcasterNativeInterface broadcastNativeInterface =
+ requireNonNull(LeAudioBroadcasterNativeInterface.getInstance());
+ broadcastNativeInterface.init();
+ mLeAudioBroadcasterNativeInterface = Optional.of(broadcastNativeInterface);
+
+ mask |= LeAudioTmapGattServer.TMAP_ROLE_FLAG_BMS;
+ } else {
+ mLeAudioBroadcasterNativeInterface = Optional.empty();
+ Log.w(TAG, "Le Audio Broadcasts not supported.");
+ }
+ mTmapRoleMask = mask;
} else {
- mTmapRoleMask =
- LeAudioTmapGattServer.TMAP_ROLE_FLAG_CG
- | LeAudioTmapGattServer.TMAP_ROLE_FLAG_UMS;
- mLeAudioBroadcasterNativeInterface = Optional.empty();
- Log.w(TAG, "Le Audio Broadcasts not supported.");
+ if ((mAdapterService.getSupportedProfilesBitMask()
+ & (1 << BluetoothProfile.LE_AUDIO_BROADCAST))
+ != 0) {
+ Log.i(TAG, "Init Le Audio broadcaster");
+ LeAudioBroadcasterNativeInterface broadcastNativeInterface =
+ requireNonNull(LeAudioBroadcasterNativeInterface.getInstance());
+ broadcastNativeInterface.init();
+ mLeAudioBroadcasterNativeInterface = Optional.of(broadcastNativeInterface);
+ mTmapRoleMask =
+ LeAudioTmapGattServer.TMAP_ROLE_FLAG_CG
+ | LeAudioTmapGattServer.TMAP_ROLE_FLAG_UMS
+ | LeAudioTmapGattServer.TMAP_ROLE_FLAG_BMS;
+ } else {
+ mTmapRoleMask =
+ LeAudioTmapGattServer.TMAP_ROLE_FLAG_CG
+ | LeAudioTmapGattServer.TMAP_ROLE_FLAG_UMS;
+ mLeAudioBroadcasterNativeInterface = Optional.empty();
+ Log.w(TAG, "Le Audio Broadcasts not supported.");
+ }
}
mTmapStarted = registerTmap();
@@ -302,6 +326,15 @@ public class LeAudioService extends ProfileService {
}
}
+ private boolean isProfileSupported(int profile) {
+ return (mAdapterService.getSupportedProfilesBitMask() & (1 << profile)) != 0;
+ }
+
+ @VisibleForTesting
+ int getTmapRoleMask() {
+ return mTmapRoleMask;
+ }
+
private class LeAudioGroupDescriptor {
LeAudioGroupDescriptor(int groupId, boolean isInbandRingtoneEnabled) {
mGroupId = groupId;
@@ -586,7 +619,7 @@ public class LeAudioService extends ProfileService {
@Override
protected IProfileServiceBinder initBinder() {
- return new BluetoothLeAudioBinder(this);
+ return new LeAudioServiceBinder(this);
}
public static boolean isEnabled() {
@@ -770,12 +803,12 @@ public class LeAudioService extends ProfileService {
mLeAudioBroadcasterNativeInterface.ifPresent(i -> i.cleanup());
- try {
- mStateMachinesThread.quitSafely();
- mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS);
- } catch (InterruptedException e) {
- // Do not rethrow as we are shutting down anyway
- }
+ try {
+ mStateMachinesThread.quitSafely();
+ mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS);
+ } catch (InterruptedException e) {
+ // Do not rethrow as we are shutting down anyway
+ }
mAudioManager.unregisterAudioDeviceCallback(mAudioManagerAudioDeviceCallback);
@@ -1799,8 +1832,10 @@ public class LeAudioService extends ProfileService {
if (device != null && mActiveAudioInDevice != null) {
LeAudioDeviceDescriptor deviceDescriptor = getDeviceDescriptor(mActiveAudioInDevice);
if (deviceDescriptor == null) {
- Log.e(TAG, "updateActiveInDevice: No valid descriptor for device: "
- + mActiveAudioInDevice);
+ Log.e(
+ TAG,
+ "updateActiveInDevice: No valid descriptor for device: "
+ + mActiveAudioInDevice);
return false;
}
@@ -1865,8 +1900,10 @@ public class LeAudioService extends ProfileService {
if (device != null && mActiveAudioOutDevice != null) {
LeAudioDeviceDescriptor deviceDescriptor = getDeviceDescriptor(mActiveAudioOutDevice);
if (deviceDescriptor == null) {
- Log.e(TAG, "updateActiveOutDevice: No valid descriptor for device: "
- + mActiveAudioOutDevice);
+ Log.e(
+ TAG,
+ "updateActiveOutDevice: No valid descriptor for device: "
+ + mActiveAudioOutDevice);
return false;
}
@@ -2094,9 +2131,7 @@ public class LeAudioService extends ProfileService {
Log.d(TAG, "Scanner is not running (mScannerId=" + mScannerId + ")");
return;
}
- mAdapterService
- .getBluetoothScanController()
- .stopScanInternal(mScannerId);
+ mAdapterService.getBluetoothScanController().stopScanInternal(mScannerId);
mAdapterService.getBluetoothScanController().unregisterScannerInternal(mScannerId);
mScannerId = SCANNER_NOT_INITIALIZED;
@@ -3191,8 +3226,10 @@ public class LeAudioService extends ProfileService {
boolean ringtoneContextAvailable = false;
if (groupDescriptor.mAvailableContexts != null) {
- ringtoneContextAvailable = ((groupDescriptor.mAvailableContexts &
- BluetoothLeAudio.CONTEXT_TYPE_RINGTONE) != 0);
+ ringtoneContextAvailable =
+ ((groupDescriptor.mAvailableContexts
+ & BluetoothLeAudio.CONTEXT_TYPE_RINGTONE)
+ != 0);
}
/* Enables in-band ringtone only for the currently active device or
@@ -3689,9 +3726,7 @@ public class LeAudioService extends ProfileService {
} else if (isInitial) {
Log.i(
TAG,
- " New group "
- + groupId
- + " with no context types available");
+ " New group " + groupId + " with no context types available");
descriptor.mInactivatedDueToContextType = true;
}
return;
@@ -3759,9 +3794,7 @@ public class LeAudioService extends ProfileService {
{
LeAudioGroupDescriptor descriptor = getGroupDescriptor(groupId);
if (descriptor == null) {
- Log.e(
- TAG,
- "deviceDisconnected: no descriptors for group: " + groupId);
+ Log.e(TAG, "deviceDisconnected: no descriptors for group: " + groupId);
return;
}
@@ -4314,7 +4347,8 @@ public class LeAudioService extends ProfileService {
if (getConnectedPeerDevices(groupId).isEmpty()) {
descriptor.mIsConnected = false;
descriptor.mAutoActiveModeEnabled = true;
- descriptor.mAvailableContexts = Flags.leaudioUnicastNoAvailableContexts() ? null : 0;
+ descriptor.mAvailableContexts =
+ Flags.leaudioUnicastNoAvailableContexts() ? null : 0;
if (descriptor.isActive()) {
/* Notify Native layer */
removeActiveDevice(hasFallbackDevice);
@@ -5489,12 +5523,15 @@ public class LeAudioService extends ProfileService {
* device should be removed from active devices.
*/
int newDirection = AUDIO_DIRECTION_NONE;
- int oldDirection = oldFallbackGroupDescriptor != null
- ? oldFallbackGroupDescriptor.mDirection : AUDIO_DIRECTION_NONE;
+ int oldDirection =
+ oldFallbackGroupDescriptor != null
+ ? oldFallbackGroupDescriptor.mDirection
+ : AUDIO_DIRECTION_NONE;
boolean notifyAndUpdateInactiveOutDeviceOnly = false;
- boolean hasFallbackDeviceWhenGettingInactive = oldFallbackGroupDescriptor != null
- ? oldFallbackGroupDescriptor.mHasFallbackDeviceWhenGettingInactive
- : false;
+ boolean hasFallbackDeviceWhenGettingInactive =
+ oldFallbackGroupDescriptor != null
+ ? oldFallbackGroupDescriptor.mHasFallbackDeviceWhenGettingInactive
+ : false;
if (groupId != LE_AUDIO_GROUP_ID_INVALID) {
newDirection = AUDIO_DIRECTION_INPUT_BIT;
notifyAndUpdateInactiveOutDeviceOnly = true;
@@ -5688,525 +5725,6 @@ public class LeAudioService extends ProfileService {
}
}
- /** Binder object: must be a static class or memory leak may occur */
- @VisibleForTesting
- static class BluetoothLeAudioBinder extends IBluetoothLeAudio.Stub
- implements IProfileServiceBinder {
- private LeAudioService mService;
-
- BluetoothLeAudioBinder(LeAudioService svc) {
- mService = svc;
- }
-
- @Override
- public void cleanup() {
- mService = null;
- }
-
- @RequiresPermission(BLUETOOTH_CONNECT)
- private LeAudioService getServiceAndEnforceConnect(AttributionSource source) {
- requireNonNull(source);
- // Cache mService because it can change while getService is called
- LeAudioService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
- return service;
- }
-
- private LeAudioService getService() {
- // Cache mService because it can change while getService is called
- LeAudioService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)) {
- return null;
- }
- return service;
- }
-
- @Override
- public boolean connect(BluetoothDevice device, AttributionSource source) {
- requireNonNull(device);
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return false;
- }
-
- return service.connect(device);
- }
-
- @Override
- public boolean disconnect(BluetoothDevice device, AttributionSource source) {
- requireNonNull(device);
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return false;
- }
-
- return service.disconnect(device);
- }
-
- @Override
- public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- return service.getConnectedDevices();
- }
-
- @Override
- public BluetoothDevice getConnectedGroupLeadDevice(int groupId, AttributionSource source) {
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return null;
- }
-
- return service.getConnectedGroupLeadDevice(groupId);
- }
-
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(
- int[] states, AttributionSource source) {
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- return service.getDevicesMatchingConnectionStates(states);
- }
-
- @Override
- public int getConnectionState(BluetoothDevice device, AttributionSource source) {
- requireNonNull(device);
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return STATE_DISCONNECTED;
- }
-
- return service.getConnectionState(device);
- }
-
- @Override
- public boolean setActiveDevice(BluetoothDevice device, AttributionSource source) {
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return false;
- }
-
- if (device == null) {
- return service.removeActiveDevice(true);
- } else {
- return service.setActiveDevice(device);
- }
- }
-
- @Override
- public List<BluetoothDevice> getActiveDevices(AttributionSource source) {
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- return service.getActiveDevices();
- }
-
- @Override
- public int getAudioLocation(BluetoothDevice device, AttributionSource source) {
- requireNonNull(device);
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return BluetoothLeAudio.AUDIO_LOCATION_INVALID;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getAudioLocation(device);
- }
-
- @Override
- public boolean isInbandRingtoneEnabled(AttributionSource source, int groupId) {
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.isInbandRingtoneEnabled(groupId);
- }
-
- @Override
- public boolean setConnectionPolicy(
- BluetoothDevice device, int connectionPolicy, AttributionSource source) {
- requireNonNull(device);
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.setConnectionPolicy(device, connectionPolicy);
- }
-
- @Override
- public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
- requireNonNull(device);
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return CONNECTION_POLICY_UNKNOWN;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getConnectionPolicy(device);
- }
-
- @Override
- public void setCcidInformation(
- ParcelUuid userUuid, int ccid, int contextType, AttributionSource source) {
- requireNonNull(userUuid);
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.setCcidInformation(userUuid, ccid, contextType);
- }
-
- @Override
- public int getGroupId(BluetoothDevice device, AttributionSource source) {
- requireNonNull(device);
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return LE_AUDIO_GROUP_ID_INVALID;
- }
-
- return service.getGroupId(device);
- }
-
- @Override
- public boolean groupAddNode(int groupId, BluetoothDevice device, AttributionSource source) {
- requireNonNull(device);
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.groupAddNode(groupId, device);
- }
-
- @Override
- public void setInCall(boolean inCall, AttributionSource source) {
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.setInCall(inCall);
- }
-
- @Override
- public void setInactiveForHfpHandover(
- BluetoothDevice hfpHandoverDevice, AttributionSource source) {
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.setInactiveForHfpHandover(hfpHandoverDevice);
- }
-
- @Override
- public boolean groupRemoveNode(
- int groupId, BluetoothDevice device, AttributionSource source) {
- requireNonNull(device);
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.groupRemoveNode(groupId, device);
- }
-
- @Override
- public void setVolume(int volume, AttributionSource source) {
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.setVolume(volume);
- }
-
- @Override
- public void registerCallback(IBluetoothLeAudioCallback callback, AttributionSource source) {
- requireNonNull(callback);
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- service.registerCallback(callback);
- }
-
- @Override
- public void unregisterCallback(
- IBluetoothLeAudioCallback callback, AttributionSource source) {
- requireNonNull(callback);
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- service.unregisterCallback(callback);
- }
-
- @Override
- public void registerLeBroadcastCallback(
- IBluetoothLeBroadcastCallback callback, AttributionSource source) {
- requireNonNull(callback);
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.registerLeBroadcastCallback(callback);
- }
-
- @Override
- public void unregisterLeBroadcastCallback(
- IBluetoothLeBroadcastCallback callback, AttributionSource source) {
- requireNonNull(callback);
- requireNonNull(source);
-
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.unregisterLeBroadcastCallback(callback);
- }
-
- @Override
- public void startBroadcast(
- BluetoothLeBroadcastSettings broadcastSettings, AttributionSource source) {
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.createBroadcast(broadcastSettings);
- }
-
- @Override
- public void stopBroadcast(int broadcastId, AttributionSource source) {
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.stopBroadcast(broadcastId);
- }
-
- @Override
- public void updateBroadcast(
- int broadcastId,
- BluetoothLeBroadcastSettings broadcastSettings,
- AttributionSource source) {
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.updateBroadcast(broadcastId, broadcastSettings);
- }
-
- @Override
- public boolean isPlaying(int broadcastId, AttributionSource source) {
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.isPlaying(broadcastId);
- }
-
- @Override
- public List<BluetoothLeBroadcastMetadata> getAllBroadcastMetadata(
- AttributionSource source) {
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getAllBroadcastMetadata();
- }
-
- @Override
- public int getMaximumNumberOfBroadcasts() {
- LeAudioService service = getService();
- if (service == null) {
- return 0;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getMaximumNumberOfBroadcasts();
- }
-
- @Override
- public int getMaximumStreamsPerBroadcast() {
- LeAudioService service = getService();
- if (service == null) {
- return 0;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getMaximumStreamsPerBroadcast();
- }
-
- @Override
- public int getMaximumSubgroupsPerBroadcast() {
- LeAudioService service = getService();
- if (service == null) {
- return 0;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getMaximumSubgroupsPerBroadcast();
- }
-
- @Override
- public BluetoothLeAudioCodecStatus getCodecStatus(int groupId, AttributionSource source) {
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return null;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getCodecStatus(groupId);
- }
-
- @Override
- public void setCodecConfigPreference(
- int groupId,
- BluetoothLeAudioCodecConfig inputCodecConfig,
- BluetoothLeAudioCodecConfig outputCodecConfig,
- AttributionSource source) {
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.setCodecConfigPreference(groupId, inputCodecConfig, outputCodecConfig);
- }
-
- @Override
- public void setBroadcastToUnicastFallbackGroup(int groupId, AttributionSource source) {
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.setBroadcastToUnicastFallbackGroup(groupId);
- }
-
- @Override
- public int getBroadcastToUnicastFallbackGroup(AttributionSource source) {
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return LE_AUDIO_GROUP_ID_INVALID;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getBroadcastToUnicastFallbackGroup();
- }
-
- @Override
- public boolean isBroadcastActive(AttributionSource source) {
- LeAudioService service = getServiceAndEnforceConnect(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.isBroadcastActive();
- }
- }
-
@Override
public void dump(StringBuilder sb) {
super.dump(sb);
diff --git a/android/app/src/com/android/bluetooth/le_audio/LeAudioServiceBinder.java b/android/app/src/com/android/bluetooth/le_audio/LeAudioServiceBinder.java
new file mode 100644
index 0000000000..e774c8fe33
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioServiceBinder.java
@@ -0,0 +1,548 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.le_audio;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+import static android.bluetooth.IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.RequiresPermission;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothLeAudio;
+import android.bluetooth.BluetoothLeAudioCodecConfig;
+import android.bluetooth.BluetoothLeAudioCodecStatus;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.bluetooth.BluetoothLeBroadcastSettings;
+import android.bluetooth.IBluetoothLeAudio;
+import android.bluetooth.IBluetoothLeAudioCallback;
+import android.bluetooth.IBluetoothLeBroadcastCallback;
+import android.content.AttributionSource;
+import android.os.ParcelUuid;
+
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+
+import java.util.Collections;
+import java.util.List;
+
+class LeAudioServiceBinder extends IBluetoothLeAudio.Stub implements IProfileServiceBinder {
+ private static final String TAG = LeAudioServiceBinder.class.getSimpleName();
+
+ private LeAudioService mService;
+
+ LeAudioServiceBinder(LeAudioService svc) {
+ mService = svc;
+ }
+
+ @Override
+ public void cleanup() {
+ mService = null;
+ }
+
+ private LeAudioService getService() {
+ LeAudioService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)) {
+ return null;
+ }
+ return service;
+ }
+
+ @RequiresPermission(BLUETOOTH_CONNECT)
+ private LeAudioService getServiceAndEnforceConnect(AttributionSource source) {
+ requireNonNull(source);
+ LeAudioService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
+ || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
+ return null;
+ }
+ return service;
+ }
+
+ @Override
+ public boolean connect(BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return false;
+ }
+
+ return service.connect(device);
+ }
+
+ @Override
+ public boolean disconnect(BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return false;
+ }
+ return service.disconnect(device);
+ }
+
+ @Override
+ public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getConnectedDevices();
+ }
+
+ @Override
+ public BluetoothDevice getConnectedGroupLeadDevice(int groupId, AttributionSource source) {
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return null;
+ }
+ return service.getConnectedGroupLeadDevice(groupId);
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ int[] states, AttributionSource source) {
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getDevicesMatchingConnectionStates(states);
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return STATE_DISCONNECTED;
+ }
+ return service.getConnectionState(device);
+ }
+
+ @Override
+ public boolean setActiveDevice(BluetoothDevice device, AttributionSource source) {
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return false;
+ }
+
+ if (device == null) {
+ return service.removeActiveDevice(true);
+ } else {
+ return service.setActiveDevice(device);
+ }
+ }
+
+ @Override
+ public List<BluetoothDevice> getActiveDevices(AttributionSource source) {
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getActiveDevices();
+ }
+
+ @Override
+ public int getAudioLocation(BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return BluetoothLeAudio.AUDIO_LOCATION_INVALID;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getAudioLocation(device);
+ }
+
+ @Override
+ public boolean isInbandRingtoneEnabled(AttributionSource source, int groupId) {
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.isInbandRingtoneEnabled(groupId);
+ }
+
+ @Override
+ public boolean setConnectionPolicy(
+ BluetoothDevice device, int connectionPolicy, AttributionSource source) {
+ requireNonNull(device);
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.setConnectionPolicy(device, connectionPolicy);
+ }
+
+ @Override
+ public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return CONNECTION_POLICY_UNKNOWN;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getConnectionPolicy(device);
+ }
+
+ @Override
+ public void setCcidInformation(
+ ParcelUuid userUuid, int ccid, int contextType, AttributionSource source) {
+ requireNonNull(userUuid);
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.setCcidInformation(userUuid, ccid, contextType);
+ }
+
+ @Override
+ public int getGroupId(BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return LE_AUDIO_GROUP_ID_INVALID;
+ }
+ return service.getGroupId(device);
+ }
+
+ @Override
+ public boolean groupAddNode(int groupId, BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.groupAddNode(groupId, device);
+ }
+
+ @Override
+ public void setInCall(boolean inCall, AttributionSource source) {
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.setInCall(inCall);
+ }
+
+ @Override
+ public void setInactiveForHfpHandover(
+ BluetoothDevice hfpHandoverDevice, AttributionSource source) {
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.setInactiveForHfpHandover(hfpHandoverDevice);
+ }
+
+ @Override
+ public boolean groupRemoveNode(int groupId, BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.groupRemoveNode(groupId, device);
+ }
+
+ @Override
+ public void setVolume(int volume, AttributionSource source) {
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.setVolume(volume);
+ }
+
+ @Override
+ public void registerCallback(IBluetoothLeAudioCallback callback, AttributionSource source) {
+ requireNonNull(callback);
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.registerCallback(callback);
+ }
+
+ @Override
+ public void unregisterCallback(IBluetoothLeAudioCallback callback, AttributionSource source) {
+ requireNonNull(callback);
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.unregisterCallback(callback);
+ }
+
+ @Override
+ public void registerLeBroadcastCallback(
+ IBluetoothLeBroadcastCallback callback, AttributionSource source) {
+ requireNonNull(callback);
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.registerLeBroadcastCallback(callback);
+ }
+
+ @Override
+ public void unregisterLeBroadcastCallback(
+ IBluetoothLeBroadcastCallback callback, AttributionSource source) {
+ requireNonNull(callback);
+ requireNonNull(source);
+
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.unregisterLeBroadcastCallback(callback);
+ }
+
+ @Override
+ public void startBroadcast(
+ BluetoothLeBroadcastSettings broadcastSettings, AttributionSource source) {
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.createBroadcast(broadcastSettings);
+ }
+
+ @Override
+ public void stopBroadcast(int broadcastId, AttributionSource source) {
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.stopBroadcast(broadcastId);
+ }
+
+ @Override
+ public void updateBroadcast(
+ int broadcastId,
+ BluetoothLeBroadcastSettings broadcastSettings,
+ AttributionSource source) {
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.updateBroadcast(broadcastId, broadcastSettings);
+ }
+
+ @Override
+ public boolean isPlaying(int broadcastId, AttributionSource source) {
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.isPlaying(broadcastId);
+ }
+
+ @Override
+ public List<BluetoothLeBroadcastMetadata> getAllBroadcastMetadata(AttributionSource source) {
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getAllBroadcastMetadata();
+ }
+
+ @Override
+ public int getMaximumNumberOfBroadcasts() {
+ LeAudioService service = getService();
+ if (service == null) {
+ return 0;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getMaximumNumberOfBroadcasts();
+ }
+
+ @Override
+ public int getMaximumStreamsPerBroadcast() {
+ LeAudioService service = getService();
+ if (service == null) {
+ return 0;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getMaximumStreamsPerBroadcast();
+ }
+
+ @Override
+ public int getMaximumSubgroupsPerBroadcast() {
+ LeAudioService service = getService();
+ if (service == null) {
+ return 0;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getMaximumSubgroupsPerBroadcast();
+ }
+
+ @Override
+ public BluetoothLeAudioCodecStatus getCodecStatus(int groupId, AttributionSource source) {
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return null;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getCodecStatus(groupId);
+ }
+
+ @Override
+ public void setCodecConfigPreference(
+ int groupId,
+ BluetoothLeAudioCodecConfig inputCodecConfig,
+ BluetoothLeAudioCodecConfig outputCodecConfig,
+ AttributionSource source) {
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.setCodecConfigPreference(groupId, inputCodecConfig, outputCodecConfig);
+ }
+
+ @Override
+ public void setBroadcastToUnicastFallbackGroup(int groupId, AttributionSource source) {
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.setBroadcastToUnicastFallbackGroup(groupId);
+ }
+
+ @Override
+ public int getBroadcastToUnicastFallbackGroup(AttributionSource source) {
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return LE_AUDIO_GROUP_ID_INVALID;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getBroadcastToUnicastFallbackGroup();
+ }
+
+ @Override
+ public boolean isBroadcastActive(AttributionSource source) {
+ LeAudioService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.isBroadcastActive();
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/le_audio/OWNERS b/android/app/src/com/android/bluetooth/le_audio/OWNERS
deleted file mode 100644
index a7d77894ba..0000000000
--- a/android/app/src/com/android/bluetooth/le_audio/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_leaudio
diff --git a/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java b/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java
index 4bead29e8c..07d7209b40 100644
--- a/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java
+++ b/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java
@@ -34,7 +34,6 @@ import com.android.bluetooth.BluetoothStatsLog;
import com.android.bluetooth.Utils.TimeProvider;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.MetricsLogger;
-import com.android.bluetooth.flags.Flags;
import com.android.bluetooth.util.WorkSourceUtil;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -72,6 +71,7 @@ class AppScanStats {
static boolean sIsRadioStarted = false;
static boolean sIsScreenOn = false;
static int sRadioScanAppImportance = IMPORTANCE_CACHED;
+ @Nullable static String sRadioScanAttributionTag;
@GuardedBy("sLock")
static long sRadioStartTime = 0;
@@ -133,6 +133,10 @@ class AppScanStats {
this.appImportanceOnStart = appImportanceOnStart;
this.filterString = new StringBuilder();
}
+
+ private String getAttributionTag() {
+ return attributionTag != null ? attributionTag : "";
+ }
}
private final List<LastScan> mLastScans = new ArrayList<>();
@@ -190,6 +194,7 @@ class AppScanStats {
mTimeProvider = requireNonNull(timeProvider);
}
+ @Nullable
private synchronized LastScan getScanFromScannerId(int scannerId) {
return mOngoingScans.get(scannerId);
}
@@ -389,23 +394,22 @@ class AppScanStats {
private void recordScanAppCountMetricsStart(LastScan scan) {
MetricsLogger logger = MetricsLogger.getInstance();
logger.cacheCount(BluetoothProtoEnums.LE_SCAN_COUNT_TOTAL_ENABLE, 1);
- if (Flags.bleScanAdvMetricsRedesign()) {
- logger.logAppScanStateChanged(
- mWorkSourceUtil.getUids(),
- mWorkSourceUtil.getTags(),
- true /* enabled */,
- scan.isFilterScan,
- scan.isCallbackScan,
- convertScanCallbackType(scan.scanCallbackType),
- convertScanType(scan),
- convertScanMode(scan.scanMode),
- scan.reportDelayMillis,
- 0 /* app_scan_duration_ms */,
- mOngoingScans.size(),
- sIsScreenOn,
- isAppDead,
- mAppImportance);
- }
+ logger.logAppScanStateChanged(
+ mWorkSourceUtil.getUids(),
+ mWorkSourceUtil.getTags(),
+ true /* enabled */,
+ scan.isFilterScan,
+ scan.isCallbackScan,
+ convertScanCallbackType(scan.scanCallbackType),
+ convertScanType(scan),
+ convertScanMode(scan.scanMode),
+ scan.reportDelayMillis,
+ 0 /* app_scan_duration_ms */,
+ mOngoingScans.size(),
+ sIsScreenOn,
+ isAppDead,
+ mAppImportance,
+ scan.getAttributionTag());
if (scan.isAutoBatchScan) {
logger.cacheCount(BluetoothProtoEnums.LE_SCAN_COUNT_AUTO_BATCH_ENABLE, 1);
} else if (scan.isBatchScan) {
@@ -422,23 +426,22 @@ class AppScanStats {
private void recordScanAppCountMetricsStop(LastScan scan) {
MetricsLogger logger = MetricsLogger.getInstance();
logger.cacheCount(BluetoothProtoEnums.LE_SCAN_COUNT_TOTAL_DISABLE, 1);
- if (Flags.bleScanAdvMetricsRedesign()) {
- logger.logAppScanStateChanged(
- mWorkSourceUtil.getUids(),
- mWorkSourceUtil.getTags(),
- false /* enabled */,
- scan.isFilterScan,
- scan.isCallbackScan,
- convertScanCallbackType(scan.scanCallbackType),
- convertScanType(scan),
- convertScanMode(scan.scanMode),
- scan.reportDelayMillis,
- scan.duration,
- mOngoingScans.size(),
- sIsScreenOn,
- isAppDead,
- mAppImportance);
- }
+ logger.logAppScanStateChanged(
+ mWorkSourceUtil.getUids(),
+ mWorkSourceUtil.getTags(),
+ false /* enabled */,
+ scan.isFilterScan,
+ scan.isCallbackScan,
+ convertScanCallbackType(scan.scanCallbackType),
+ convertScanType(scan),
+ convertScanMode(scan.scanMode),
+ scan.reportDelayMillis,
+ scan.duration,
+ mOngoingScans.size(),
+ sIsScreenOn,
+ isAppDead,
+ mAppImportance,
+ scan.getAttributionTag());
if (scan.isAutoBatchScan) {
logger.cacheCount(BluetoothProtoEnums.LE_SCAN_COUNT_AUTO_BATCH_DISABLE, 1);
} else if (scan.isBatchScan) {
@@ -515,46 +518,43 @@ class AppScanStats {
}
synchronized void recordScanTimeoutCountMetrics(int scannerId, long scanTimeoutMillis) {
- if (Flags.bleScanAdvMetricsRedesign()) {
- BluetoothStatsLog.write(
- BluetoothStatsLog.LE_SCAN_ABUSED,
- mWorkSourceUtil.getUids(),
- mWorkSourceUtil.getTags(),
- convertScanType(getScanFromScannerId(scannerId)),
- BluetoothStatsLog.LE_SCAN_ABUSED__LE_SCAN_ABUSE_REASON__REASON_SCAN_TIMEOUT,
- scanTimeoutMillis);
- }
+ BluetoothStatsLog.write(
+ BluetoothStatsLog.LE_SCAN_ABUSED,
+ mWorkSourceUtil.getUids(),
+ mWorkSourceUtil.getTags(),
+ convertScanType(getScanFromScannerId(scannerId)),
+ BluetoothStatsLog.LE_SCAN_ABUSED__LE_SCAN_ABUSE_REASON__REASON_SCAN_TIMEOUT,
+ scanTimeoutMillis,
+ getAttributionTagFromScannerId(scannerId));
MetricsLogger.getInstance()
.cacheCount(BluetoothProtoEnums.LE_SCAN_ABUSE_COUNT_SCAN_TIMEOUT, 1);
}
synchronized void recordHwFilterNotAvailableCountMetrics(
int scannerId, long numOfFilterSupported) {
- if (Flags.bleScanAdvMetricsRedesign()) {
- BluetoothStatsLog.write(
- BluetoothStatsLog.LE_SCAN_ABUSED,
- mWorkSourceUtil.getUids(),
- mWorkSourceUtil.getTags(),
- convertScanType(getScanFromScannerId(scannerId)),
- BluetoothStatsLog.LE_SCAN_ABUSED__LE_SCAN_ABUSE_REASON__REASON_HW_FILTER_NA,
- numOfFilterSupported);
- }
+ BluetoothStatsLog.write(
+ BluetoothStatsLog.LE_SCAN_ABUSED,
+ mWorkSourceUtil.getUids(),
+ mWorkSourceUtil.getTags(),
+ convertScanType(getScanFromScannerId(scannerId)),
+ BluetoothStatsLog.LE_SCAN_ABUSED__LE_SCAN_ABUSE_REASON__REASON_HW_FILTER_NA,
+ numOfFilterSupported,
+ getAttributionTagFromScannerId(scannerId));
MetricsLogger.getInstance()
.cacheCount(BluetoothProtoEnums.LE_SCAN_ABUSE_COUNT_HW_FILTER_NOT_AVAILABLE, 1);
}
synchronized void recordTrackingHwFilterNotAvailableCountMetrics(
int scannerId, long numOfTrackableAdv) {
- if (Flags.bleScanAdvMetricsRedesign()) {
- BluetoothStatsLog.write(
- BluetoothStatsLog.LE_SCAN_ABUSED,
- mWorkSourceUtil.getUids(),
- mWorkSourceUtil.getTags(),
- convertScanType(getScanFromScannerId(scannerId)),
- BluetoothStatsLog
- .LE_SCAN_ABUSED__LE_SCAN_ABUSE_REASON__REASON_TRACKING_HW_FILTER_NA,
- numOfTrackableAdv);
- }
+ BluetoothStatsLog.write(
+ BluetoothStatsLog.LE_SCAN_ABUSED,
+ mWorkSourceUtil.getUids(),
+ mWorkSourceUtil.getTags(),
+ convertScanType(getScanFromScannerId(scannerId)),
+ BluetoothStatsLog
+ .LE_SCAN_ABUSED__LE_SCAN_ABUSE_REASON__REASON_TRACKING_HW_FILTER_NA,
+ numOfTrackableAdv,
+ getAttributionTagFromScannerId(scannerId));
MetricsLogger.getInstance()
.cacheCount(
BluetoothProtoEnums.LE_SCAN_ABUSE_COUNT_TRACKING_HW_FILTER_NOT_AVAILABLE,
@@ -586,6 +586,7 @@ class AppScanStats {
sRadioScanIntervalMs = scanIntervalMs;
sIsRadioStarted = true;
sRadioScanAppImportance = stats.mAppImportance;
+ sRadioScanAttributionTag = stats.getAttributionTagFromScannerId(scannerId);
}
return true;
}
@@ -596,10 +597,6 @@ class AppScanStats {
return false;
}
recordScanRadioDurationMetrics(timeProvider);
- if (!Flags.bleScanAdvMetricsRedesign()) {
- sRadioStartTime = 0;
- sIsRadioStarted = false;
- }
}
return true;
}
@@ -615,20 +612,19 @@ class AppScanStats {
double scanWeight = getScanWeight(sRadioScanMode) * 0.01;
long weightedDuration = (long) (radioScanDuration * scanWeight);
- if (Flags.bleScanAdvMetricsRedesign()) {
- logger.logRadioScanStopped(
- getRadioScanUids(),
- getRadioScanTags(),
- sRadioScanType,
- convertScanMode(sRadioScanMode),
- sRadioScanIntervalMs,
- sRadioScanWindowMs,
- sIsScreenOn,
- radioScanDuration,
- sRadioScanAppImportance);
- sRadioStartTime = 0;
- sIsRadioStarted = false;
- }
+ logger.logRadioScanStopped(
+ getRadioScanUids(),
+ getRadioScanTags(),
+ sRadioScanType,
+ convertScanMode(sRadioScanMode),
+ sRadioScanIntervalMs,
+ sRadioScanWindowMs,
+ sIsScreenOn,
+ radioScanDuration,
+ sRadioScanAppImportance,
+ getRadioScanAttributionTag());
+ sRadioStartTime = 0;
+ sIsRadioStarted = false;
if (weightedDuration > 0) {
logger.cacheCount(BluetoothProtoEnums.LE_SCAN_RADIO_DURATION_REGULAR, weightedDuration);
if (sIsScreenOn) {
@@ -659,6 +655,12 @@ class AppScanStats {
}
}
+ private static String getRadioScanAttributionTag() {
+ synchronized (sLock) {
+ return sRadioScanAttributionTag != null ? sRadioScanAttributionTag : "";
+ }
+ }
+
@GuardedBy("sLock")
private static void recordScreenOnOffMetrics(boolean isScreenOn) {
if (isScreenOn) {
@@ -692,15 +694,14 @@ class AppScanStats {
if (!sIsRadioStarted) {
return;
}
- if (Flags.bleScanAdvMetricsRedesign()) {
- BluetoothStatsLog.write(
- BluetoothStatsLog.LE_SCAN_RESULT_RECEIVED,
- getRadioScanUids(),
- getRadioScanTags(),
- 1 /* num_results */,
- BluetoothStatsLog.LE_SCAN_RESULT_RECEIVED__LE_SCAN_TYPE__SCAN_TYPE_REGULAR,
- sIsScreenOn);
- }
+ BluetoothStatsLog.write(
+ BluetoothStatsLog.LE_SCAN_RESULT_RECEIVED,
+ getRadioScanUids(),
+ getRadioScanTags(),
+ 1 /* num_results */,
+ BluetoothStatsLog.LE_SCAN_RESULT_RECEIVED__LE_SCAN_TYPE__SCAN_TYPE_REGULAR,
+ sIsScreenOn,
+ getRadioScanAttributionTag());
MetricsLogger logger = MetricsLogger.getInstance();
logger.cacheCount(BluetoothProtoEnums.LE_SCAN_RESULTS_COUNT_REGULAR, 1);
if (sIsScreenOn) {
@@ -716,15 +717,14 @@ class AppScanStats {
synchronized (sLock) {
isScreenOn = sIsScreenOn;
}
- if (Flags.bleScanAdvMetricsRedesign()) {
- BluetoothStatsLog.write(
- BluetoothStatsLog.LE_SCAN_RESULT_RECEIVED,
- getRadioScanUids(),
- getRadioScanTags(),
- numRecords,
- BluetoothStatsLog.LE_SCAN_RESULT_RECEIVED__LE_SCAN_TYPE__SCAN_TYPE_BATCH,
- sIsScreenOn);
- }
+ BluetoothStatsLog.write(
+ BluetoothStatsLog.LE_SCAN_RESULT_RECEIVED,
+ getRadioScanUids(),
+ getRadioScanTags(),
+ numRecords,
+ BluetoothStatsLog.LE_SCAN_RESULT_RECEIVED__LE_SCAN_TYPE__SCAN_TYPE_BATCH,
+ sIsScreenOn,
+ getRadioScanAttributionTag());
MetricsLogger logger = MetricsLogger.getInstance();
logger.cacheCount(BluetoothProtoEnums.LE_SCAN_RESULTS_COUNT_BATCH_BUNDLE, 1);
logger.cacheCount(BluetoothProtoEnums.LE_SCAN_RESULTS_COUNT_BATCH, numRecords);
@@ -829,6 +829,11 @@ class AppScanStats {
< LARGE_SCAN_TIME_GAP_MS);
}
+ private String getAttributionTagFromScannerId(int scannerId) {
+ LastScan scan = getScanFromScannerId(scannerId);
+ return scan == null ? "" : scan.getAttributionTag();
+ }
+
private static String filterToStringWithoutNullParam(ScanFilter filter) {
StringBuilder filterString = new StringBuilder("BluetoothLeScanFilter [");
if (filter.getDeviceName() != null) {
diff --git a/android/app/src/com/android/bluetooth/le_scan/ScanController.java b/android/app/src/com/android/bluetooth/le_scan/ScanController.java
index 82b8e10dd7..2fc20d8314 100644
--- a/android/app/src/com/android/bluetooth/le_scan/ScanController.java
+++ b/android/app/src/com/android/bluetooth/le_scan/ScanController.java
@@ -22,6 +22,7 @@ import static android.Manifest.permission.UPDATE_DEVICE_STATS;
import static android.bluetooth.BluetoothUtils.extractBytes;
import static com.android.bluetooth.Utils.checkCallerTargetSdk;
+import static com.android.bluetooth.Utils.checkScanPermissionForDataDelivery;
import static com.android.bluetooth.flags.Flags.leaudioBassScanWithInternalScanController;
import static java.util.Objects.requireNonNull;
@@ -1082,8 +1083,7 @@ public class ScanController {
@RequiresPermission(BLUETOOTH_SCAN)
void registerScanner(
IScannerCallback callback, WorkSource workSource, AttributionSource source) {
- if (!Utils.checkScanPermissionForDataDelivery(
- mAdapterService, source, "ScanController registerScanner")) {
+ if (!checkScanPermissionForDataDelivery(mAdapterService, source, TAG, "registerScanner")) {
return;
}
@@ -1116,8 +1116,8 @@ public class ScanController {
@RequiresPermission(BLUETOOTH_SCAN)
void unregisterScanner(int scannerId, AttributionSource source) {
- if (!Utils.checkScanPermissionForDataDelivery(
- mAdapterService, source, "ScanController unregisterScanner")) {
+ if (!checkScanPermissionForDataDelivery(
+ mAdapterService, source, TAG, "unregisterScanner")) {
return;
}
@@ -1163,7 +1163,7 @@ public class ScanController {
List<ScanFilter> filters,
AttributionSource source) {
Log.d(TAG, "Start scan with filters");
- if (!Utils.checkScanPermissionForDataDelivery(mAdapterService, source, "Starting scan.")) {
+ if (!checkScanPermissionForDataDelivery(mAdapterService, source, TAG, "startScan")) {
return;
}
@@ -1255,7 +1255,8 @@ public class ScanController {
List<ScanFilter> filters,
AttributionSource source) {
Log.d(TAG, "Start scan with filters, for PendingIntent");
- if (!Utils.checkScanPermissionForDataDelivery(mAdapterService, source, "Starting scan.")) {
+ if (!checkScanPermissionForDataDelivery(
+ mAdapterService, source, TAG, "registerPiAndStartScan")) {
return;
}
@@ -1359,8 +1360,8 @@ public class ScanController {
@RequiresPermission(BLUETOOTH_SCAN)
void flushPendingBatchResults(int scannerId, AttributionSource source) {
- if (!Utils.checkScanPermissionForDataDelivery(
- mAdapterService, source, "ScanController flushPendingBatchResults")) {
+ if (!checkScanPermissionForDataDelivery(
+ mAdapterService, source, TAG, "flushPendingBatchResults")) {
return;
}
flushPendingBatchResultsInternal(scannerId);
@@ -1373,8 +1374,7 @@ public class ScanController {
@RequiresPermission(BLUETOOTH_SCAN)
void stopScan(int scannerId, AttributionSource source) {
- if (!Utils.checkScanPermissionForDataDelivery(
- mAdapterService, source, "ScanController stopScan")) {
+ if (!checkScanPermissionForDataDelivery(mAdapterService, source, TAG, "stopScan")) {
return;
}
stopScanInternal(scannerId);
@@ -1396,8 +1396,7 @@ public class ScanController {
@RequiresPermission(BLUETOOTH_SCAN)
void stopScan(PendingIntent intent, AttributionSource source) {
- if (!Utils.checkScanPermissionForDataDelivery(
- mAdapterService, source, "ScanController stopScan")) {
+ if (!checkScanPermissionForDataDelivery(mAdapterService, source, TAG, "stopScan")) {
return;
}
stopScanInternal(intent);
@@ -1426,8 +1425,7 @@ public class ScanController {
int timeout,
IPeriodicAdvertisingCallback callback,
AttributionSource source) {
- if (!Utils.checkScanPermissionForDataDelivery(
- mAdapterService, source, "ScanController registerSync")) {
+ if (!checkScanPermissionForDataDelivery(mAdapterService, source, TAG, "registerSync")) {
return;
}
mPeriodicScanManager.startSync(scanResult, skip, timeout, callback);
@@ -1435,8 +1433,7 @@ public class ScanController {
@RequiresPermission(BLUETOOTH_SCAN)
void unregisterSync(IPeriodicAdvertisingCallback callback, AttributionSource source) {
- if (!Utils.checkScanPermissionForDataDelivery(
- mAdapterService, source, "ScanController unregisterSync")) {
+ if (!checkScanPermissionForDataDelivery(mAdapterService, source, TAG, "unregisterSync")) {
return;
}
mPeriodicScanManager.stopSync(callback);
@@ -1445,8 +1442,7 @@ public class ScanController {
@RequiresPermission(BLUETOOTH_SCAN)
void transferSync(
BluetoothDevice bda, int serviceData, int syncHandle, AttributionSource source) {
- if (!Utils.checkScanPermissionForDataDelivery(
- mAdapterService, source, "ScanController transferSync")) {
+ if (!checkScanPermissionForDataDelivery(mAdapterService, source, TAG, "transferSync")) {
return;
}
mPeriodicScanManager.transferSync(bda, serviceData, syncHandle);
@@ -1459,8 +1455,7 @@ public class ScanController {
int advHandle,
IPeriodicAdvertisingCallback callback,
AttributionSource source) {
- if (!Utils.checkScanPermissionForDataDelivery(
- mAdapterService, source, "ScanController transferSetInfo")) {
+ if (!checkScanPermissionForDataDelivery(mAdapterService, source, TAG, "transferSetInfo")) {
return;
}
mPeriodicScanManager.transferSetInfo(bda, serviceData, advHandle, callback);
@@ -1468,8 +1463,8 @@ public class ScanController {
@RequiresPermission(BLUETOOTH_SCAN)
int numHwTrackFiltersAvailable(AttributionSource source) {
- if (!Utils.checkScanPermissionForDataDelivery(
- mAdapterService, source, "ScanController numHwTrackFiltersAvailable")) {
+ if (!checkScanPermissionForDataDelivery(
+ mAdapterService, source, TAG, "numHwTrackFiltersAvailable")) {
return 0;
}
return (mAdapterService.getTotalNumOfTrackableAdvertisements()
diff --git a/android/app/src/com/android/bluetooth/le_scan/ScanManager.java b/android/app/src/com/android/bluetooth/le_scan/ScanManager.java
index cf6ef7d928..e31bd36bbb 100644
--- a/android/app/src/com/android/bluetooth/le_scan/ScanManager.java
+++ b/android/app/src/com/android/bluetooth/le_scan/ScanManager.java
@@ -1292,18 +1292,6 @@ public class ScanManager {
&& client.mSettings.getScanMode() != ScanSettings.SCAN_MODE_OPPORTUNISTIC) {
Log.d(TAG, "start gattClientScanNative from startRegularScan()");
mNativeInterface.gattClientScan(true);
- if (!Flags.bleScanAdvMetricsRedesign()) {
- if (client.mStats != null
- && !AppScanStats.recordScanRadioStart(
- client.mSettings.getScanMode(),
- client.mScannerId,
- client.mStats,
- getScanWindowMillis(client.mSettings),
- getScanIntervalMillis(client.mSettings),
- mTimeProvider)) {
- Log.w(TAG, "Scan radio already started");
- }
- }
}
}
diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapService.java b/android/app/src/com/android/bluetooth/map/BluetoothMapService.java
index bac8bdc247..b43af84dcc 100644
--- a/android/app/src/com/android/bluetooth/map/BluetoothMapService.java
+++ b/android/app/src/com/android/bluetooth/map/BluetoothMapService.java
@@ -18,7 +18,6 @@ package com.android.bluetooth.map;
import static android.Manifest.permission.BLUETOOTH_CONNECT;
import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
@@ -33,9 +32,7 @@ import android.bluetooth.BluetoothMap;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothProtoEnums;
import android.bluetooth.BluetoothUuid;
-import android.bluetooth.IBluetoothMap;
import android.bluetooth.SdpMnsRecord;
-import android.content.AttributionSource;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -66,7 +63,6 @@ import com.android.internal.annotations.VisibleForTesting;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -149,7 +145,6 @@ public class BluetoothMapService extends ProfileService {
private static BluetoothMapService sBluetoothMapService;
-
private static final ParcelUuid[] MAP_UUIDS = {
BluetoothUuid.MAP, BluetoothUuid.MNS,
};
@@ -705,7 +700,7 @@ public class BluetoothMapService extends ProfileService {
@Override
protected IProfileServiceBinder initBinder() {
- return new BluetoothMapBinder(this);
+ return new BluetoothMapServiceBinder(this);
}
/**
@@ -1190,227 +1185,6 @@ public class BluetoothMapService extends ProfileService {
}
}
- // Binder object: Must be static class or memory leak may occur
-
- /**
- * This class implements the IBluetoothMap interface - or actually it validates the
- * preconditions for calling the actual functionality in the MapService, and calls it.
- */
- @VisibleForTesting
- static class BluetoothMapBinder extends IBluetoothMap.Stub implements IProfileServiceBinder {
- private BluetoothMapService mService;
-
- BluetoothMapBinder(BluetoothMapService service) {
- mService = service;
- }
-
- @Override
- public synchronized void cleanup() {
- mService = null;
- }
-
- @RequiresPermission(BLUETOOTH_CONNECT)
- private BluetoothMapService getService(AttributionSource source) {
- // Cache mService because it can change while getService is called
- BluetoothMapService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
- return service;
- }
-
- @Override
- public int getState(AttributionSource source) {
- Log.v(TAG, "getState()");
- try {
- BluetoothMapService service = getService(source);
- if (service == null) {
- return BluetoothMap.STATE_DISCONNECTED;
- }
-
- return service.getState();
- } catch (RuntimeException e) {
- ContentProfileErrorReportUtils.report(
- BluetoothProfile.MAP,
- BluetoothProtoEnums.BLUETOOTH_MAP_SERVICE,
- BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION,
- 16);
- throw e;
- }
- }
-
- @Override
- public BluetoothDevice getClient(AttributionSource source) {
- Log.v(TAG, "getClient()");
- try {
- BluetoothMapService service = getService(source);
- if (service == null) {
- Log.v(TAG, "getClient() - no service - returning " + null);
- return null;
- }
- BluetoothDevice client = service.getRemoteDevice();
- Log.v(TAG, "getClient() - returning " + client);
- return client;
- } catch (RuntimeException e) {
- ContentProfileErrorReportUtils.report(
- BluetoothProfile.MAP,
- BluetoothProtoEnums.BLUETOOTH_MAP_SERVICE,
- BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION,
- 17);
- throw e;
- }
- }
-
- @Override
- public boolean isConnected(BluetoothDevice device, AttributionSource source) {
- Log.v(TAG, "isConnected()");
- try {
- BluetoothMapService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.getConnectionState(device) == STATE_CONNECTED;
- } catch (RuntimeException e) {
- ContentProfileErrorReportUtils.report(
- BluetoothProfile.MAP,
- BluetoothProtoEnums.BLUETOOTH_MAP_SERVICE,
- BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION,
- 18);
- throw e;
- }
- }
-
- @Override
- public boolean disconnect(BluetoothDevice device, AttributionSource source) {
- Log.v(TAG, "disconnect()");
- try {
- BluetoothMapService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.disconnect(device);
- return true;
- } catch (RuntimeException e) {
- ContentProfileErrorReportUtils.report(
- BluetoothProfile.MAP,
- BluetoothProtoEnums.BLUETOOTH_MAP_SERVICE,
- BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION,
- 19);
- throw e;
- }
- }
-
- @Override
- public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
- Log.v(TAG, "getConnectedDevices()");
- try {
- BluetoothMapService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getConnectedDevices();
- } catch (RuntimeException e) {
- ContentProfileErrorReportUtils.report(
- BluetoothProfile.MAP,
- BluetoothProtoEnums.BLUETOOTH_MAP_SERVICE,
- BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION,
- 20);
- throw e;
- }
- }
-
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(
- int[] states, AttributionSource source) {
- Log.v(TAG, "getDevicesMatchingConnectionStates()");
- try {
- BluetoothMapService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- return service.getDevicesMatchingConnectionStates(states);
- } catch (RuntimeException e) {
- ContentProfileErrorReportUtils.report(
- BluetoothProfile.MAP,
- BluetoothProtoEnums.BLUETOOTH_MAP_SERVICE,
- BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION,
- 21);
- throw e;
- }
- }
-
- @Override
- public int getConnectionState(BluetoothDevice device, AttributionSource source) {
- Log.v(TAG, "getConnectionState()");
- try {
- BluetoothMapService service = getService(source);
- if (service == null) {
- return STATE_DISCONNECTED;
- }
-
- return service.getConnectionState(device);
- } catch (RuntimeException e) {
- ContentProfileErrorReportUtils.report(
- BluetoothProfile.MAP,
- BluetoothProtoEnums.BLUETOOTH_MAP_SERVICE,
- BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION,
- 22);
- throw e;
- }
- }
-
- @Override
- public boolean setConnectionPolicy(
- BluetoothDevice device, int connectionPolicy, AttributionSource source) {
- try {
- BluetoothMapService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.setConnectionPolicy(device, connectionPolicy);
- } catch (RuntimeException e) {
- ContentProfileErrorReportUtils.report(
- BluetoothProfile.MAP,
- BluetoothProtoEnums.BLUETOOTH_MAP_SERVICE,
- BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION,
- 23);
- throw e;
- }
- }
-
- @Override
- public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
- try {
- BluetoothMapService service = getService(source);
- if (service == null) {
- return CONNECTION_POLICY_UNKNOWN;
- }
-
- return service.getConnectionPolicy(device);
- } catch (RuntimeException e) {
- ContentProfileErrorReportUtils.report(
- BluetoothProfile.MAP,
- BluetoothProtoEnums.BLUETOOTH_MAP_SERVICE,
- BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION,
- 24);
- throw e;
- }
- }
- }
-
@Override
public void dump(StringBuilder sb) {
super.dump(sb);
diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapServiceBinder.java b/android/app/src/com/android/bluetooth/map/BluetoothMapServiceBinder.java
new file mode 100644
index 0000000000..0706bcab6f
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/map/BluetoothMapServiceBinder.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.map;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
+import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+
+import android.annotation.RequiresPermission;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothMap;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothProtoEnums;
+import android.bluetooth.IBluetoothMap;
+import android.content.AttributionSource;
+import android.util.Log;
+
+import com.android.bluetooth.BluetoothStatsLog;
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+import com.android.bluetooth.content_profiles.ContentProfileErrorReportUtils;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * This class implements the IBluetoothMap interface - or actually it validates the preconditions
+ * for calling the actual functionality in the MapService, and calls it.
+ */
+class BluetoothMapServiceBinder extends IBluetoothMap.Stub implements IProfileServiceBinder {
+ private static final String TAG = BluetoothMapServiceBinder.class.getSimpleName();
+
+ private BluetoothMapService mService;
+
+ BluetoothMapServiceBinder(BluetoothMapService service) {
+ mService = service;
+ }
+
+ @Override
+ public synchronized void cleanup() {
+ mService = null;
+ }
+
+ @RequiresPermission(BLUETOOTH_CONNECT)
+ private BluetoothMapService getService(AttributionSource source) {
+ BluetoothMapService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
+ || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
+ return null;
+ }
+ return service;
+ }
+
+ @Override
+ public int getState(AttributionSource source) {
+ Log.v(TAG, "getState()");
+ try {
+ BluetoothMapService service = getService(source);
+ if (service == null) {
+ return BluetoothMap.STATE_DISCONNECTED;
+ }
+ return service.getState();
+ } catch (RuntimeException e) {
+ ContentProfileErrorReportUtils.report(
+ BluetoothProfile.MAP,
+ BluetoothProtoEnums.BLUETOOTH_MAP_SERVICE,
+ BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION,
+ 16);
+ throw e;
+ }
+ }
+
+ @Override
+ public BluetoothDevice getClient(AttributionSource source) {
+ Log.v(TAG, "getClient()");
+ try {
+ BluetoothMapService service = getService(source);
+ if (service == null) {
+ Log.v(TAG, "getClient() - no service - returning " + null);
+ return null;
+ }
+ BluetoothDevice client = service.getRemoteDevice();
+ Log.v(TAG, "getClient() - returning " + client);
+ return client;
+ } catch (RuntimeException e) {
+ ContentProfileErrorReportUtils.report(
+ BluetoothProfile.MAP,
+ BluetoothProtoEnums.BLUETOOTH_MAP_SERVICE,
+ BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION,
+ 17);
+ throw e;
+ }
+ }
+
+ @Override
+ public boolean isConnected(BluetoothDevice device, AttributionSource source) {
+ Log.v(TAG, "isConnected()");
+ try {
+ BluetoothMapService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.getConnectionState(device) == STATE_CONNECTED;
+ } catch (RuntimeException e) {
+ ContentProfileErrorReportUtils.report(
+ BluetoothProfile.MAP,
+ BluetoothProtoEnums.BLUETOOTH_MAP_SERVICE,
+ BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION,
+ 18);
+ throw e;
+ }
+ }
+
+ @Override
+ public boolean disconnect(BluetoothDevice device, AttributionSource source) {
+ Log.v(TAG, "disconnect()");
+ try {
+ BluetoothMapService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ service.disconnect(device);
+ return true;
+ } catch (RuntimeException e) {
+ ContentProfileErrorReportUtils.report(
+ BluetoothProfile.MAP,
+ BluetoothProtoEnums.BLUETOOTH_MAP_SERVICE,
+ BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION,
+ 19);
+ throw e;
+ }
+ }
+
+ @Override
+ public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
+ Log.v(TAG, "getConnectedDevices()");
+ try {
+ BluetoothMapService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getConnectedDevices();
+ } catch (RuntimeException e) {
+ ContentProfileErrorReportUtils.report(
+ BluetoothProfile.MAP,
+ BluetoothProtoEnums.BLUETOOTH_MAP_SERVICE,
+ BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION,
+ 20);
+ throw e;
+ }
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ int[] states, AttributionSource source) {
+ Log.v(TAG, "getDevicesMatchingConnectionStates()");
+ try {
+ BluetoothMapService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getDevicesMatchingConnectionStates(states);
+ } catch (RuntimeException e) {
+ ContentProfileErrorReportUtils.report(
+ BluetoothProfile.MAP,
+ BluetoothProtoEnums.BLUETOOTH_MAP_SERVICE,
+ BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION,
+ 21);
+ throw e;
+ }
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice device, AttributionSource source) {
+ Log.v(TAG, "getConnectionState()");
+ try {
+ BluetoothMapService service = getService(source);
+ if (service == null) {
+ return STATE_DISCONNECTED;
+ }
+ return service.getConnectionState(device);
+ } catch (RuntimeException e) {
+ ContentProfileErrorReportUtils.report(
+ BluetoothProfile.MAP,
+ BluetoothProtoEnums.BLUETOOTH_MAP_SERVICE,
+ BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION,
+ 22);
+ throw e;
+ }
+ }
+
+ @Override
+ public boolean setConnectionPolicy(
+ BluetoothDevice device, int connectionPolicy, AttributionSource source) {
+ try {
+ BluetoothMapService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.setConnectionPolicy(device, connectionPolicy);
+ } catch (RuntimeException e) {
+ ContentProfileErrorReportUtils.report(
+ BluetoothProfile.MAP,
+ BluetoothProtoEnums.BLUETOOTH_MAP_SERVICE,
+ BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION,
+ 23);
+ throw e;
+ }
+ }
+
+ @Override
+ public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
+ try {
+ BluetoothMapService service = getService(source);
+ if (service == null) {
+ return CONNECTION_POLICY_UNKNOWN;
+ }
+ return service.getConnectionPolicy(device);
+ } catch (RuntimeException e) {
+ ContentProfileErrorReportUtils.report(
+ BluetoothProfile.MAP,
+ BluetoothProtoEnums.BLUETOOTH_MAP_SERVICE,
+ BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION,
+ 24);
+ throw e;
+ }
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/map/OWNERS b/android/app/src/com/android/bluetooth/map/OWNERS
deleted file mode 100644
index 8f87191393..0000000000
--- a/android/app/src/com/android/bluetooth/map/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_content \ No newline at end of file
diff --git a/android/app/src/com/android/bluetooth/mapclient/MapClientService.java b/android/app/src/com/android/bluetooth/mapclient/MapClientService.java
index 5e2be59b11..fdecfddf15 100644
--- a/android/app/src/com/android/bluetooth/mapclient/MapClientService.java
+++ b/android/app/src/com/android/bluetooth/mapclient/MapClientService.java
@@ -16,11 +16,8 @@
package com.android.bluetooth.mapclient;
-import static android.Manifest.permission.BLUETOOTH_CONNECT;
-import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
import static android.bluetooth.BluetoothProfile.STATE_CONNECTING;
import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
@@ -28,16 +25,12 @@ import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
import static java.util.Objects.requireNonNull;
import static java.util.Objects.requireNonNullElseGet;
-import android.Manifest;
-import android.annotation.RequiresPermission;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
-import android.bluetooth.IBluetoothMapClient;
import android.bluetooth.SdpMasRecord;
-import android.content.AttributionSource;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
@@ -46,7 +39,6 @@ import android.os.Parcelable;
import android.sysprop.BluetoothProperties;
import android.util.Log;
-import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.btservice.storage.DatabaseManager;
@@ -54,7 +46,6 @@ import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -307,7 +298,7 @@ public class MapClientService extends ProfileService {
@Override
public IProfileServiceBinder initBinder() {
- return new Binder(this);
+ return new MapClientServiceBinder(this);
}
@Override
@@ -408,172 +399,6 @@ public class MapClientService extends ProfileService {
}
}
- // Binder object: Must be static class or memory leak may occur
-
- /**
- * This class implements the IClient interface - or actually it validates the preconditions for
- * calling the actual functionality in the MapClientService, and calls it.
- */
- @VisibleForTesting
- static class Binder extends IBluetoothMapClient.Stub implements IProfileServiceBinder {
- private MapClientService mService;
-
- Binder(MapClientService service) {
- mService = service;
- }
-
- @Override
- public void cleanup() {
- mService = null;
- }
-
- @RequiresPermission(BLUETOOTH_CONNECT)
- private MapClientService getService(AttributionSource source) {
- // Cache mService because it can change while getService is called
- MapClientService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !(getCallingUserHandle().isSystem()
- || Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG))
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
- return service;
- }
-
- @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED})
- private MapClientService getServiceAndEnforcePrivileged(AttributionSource source) {
- // Cache mService because it can change while getService is called
- MapClientService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !(getCallingUserHandle().isSystem()
- || Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG))
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service;
- }
-
- @Override
- public boolean connect(BluetoothDevice device, AttributionSource source) {
- Log.v(TAG, "connect()");
-
- MapClientService service = getServiceAndEnforcePrivileged(source);
- if (service == null) {
- return false;
- }
-
- return service.connect(device);
- }
-
- @Override
- public boolean disconnect(BluetoothDevice device, AttributionSource source) {
- Log.v(TAG, "disconnect()");
-
- MapClientService service = getServiceAndEnforcePrivileged(source);
- if (service == null) {
- return false;
- }
-
- return service.disconnect(device);
- }
-
- @Override
- public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
- Log.v(TAG, "getConnectedDevices()");
-
- MapClientService service = getServiceAndEnforcePrivileged(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- return service.getConnectedDevices();
- }
-
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(
- int[] states, AttributionSource source) {
- Log.v(TAG, "getDevicesMatchingConnectionStates()");
-
- MapClientService service = getServiceAndEnforcePrivileged(source);
- if (service == null) {
- return Collections.emptyList();
- }
- return service.getDevicesMatchingConnectionStates(states);
- }
-
- @Override
- public int getConnectionState(BluetoothDevice device, AttributionSource source) {
- Log.v(TAG, "getConnectionState()");
-
- MapClientService service = getServiceAndEnforcePrivileged(source);
- if (service == null) {
- return STATE_DISCONNECTED;
- }
-
- return service.getConnectionState(device);
- }
-
- @Override
- public boolean setConnectionPolicy(
- BluetoothDevice device, int connectionPolicy, AttributionSource source) {
- Log.v(TAG, "setConnectionPolicy()");
-
- MapClientService service = getServiceAndEnforcePrivileged(source);
- if (service == null) {
- return false;
- }
-
- return service.setConnectionPolicy(device, connectionPolicy);
- }
-
- @Override
- public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
- Log.v(TAG, "getConnectionPolicy()");
-
- MapClientService service = getServiceAndEnforcePrivileged(source);
- if (service == null) {
- return CONNECTION_POLICY_UNKNOWN;
- }
-
- return service.getConnectionPolicy(device);
- }
-
- @Override
- public boolean sendMessage(
- BluetoothDevice device,
- Uri[] contacts,
- String message,
- PendingIntent sentIntent,
- PendingIntent deliveredIntent,
- AttributionSource source) {
- Log.v(TAG, "sendMessage()");
-
- MapClientService service = getService(source);
- if (service == null) {
- return false;
- }
-
- Log.d(TAG, "Checking Permission of sendMessage");
- mService.enforceCallingOrSelfPermission(
- Manifest.permission.SEND_SMS, "Need SEND_SMS permission");
-
- return service.sendMessage(device, contacts, message, sentIntent, deliveredIntent);
- }
- }
-
public void aclDisconnected(BluetoothDevice device, int transport) {
mHandler.post(() -> handleAclDisconnected(device, transport));
}
diff --git a/android/app/src/com/android/bluetooth/mapclient/MapClientServiceBinder.java b/android/app/src/com/android/bluetooth/mapclient/MapClientServiceBinder.java
new file mode 100644
index 0000000000..d6be8975e8
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/mapclient/MapClientServiceBinder.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.mapclient;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+
+import android.Manifest;
+import android.annotation.RequiresPermission;
+import android.app.PendingIntent;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.IBluetoothMapClient;
+import android.content.AttributionSource;
+import android.net.Uri;
+import android.util.Log;
+
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * This class implements the IClient interface - or actually it validates the preconditions for
+ * calling the actual functionality in the MapClientService, and calls it.
+ */
+class MapClientServiceBinder extends IBluetoothMapClient.Stub implements IProfileServiceBinder {
+ private static final String TAG = MapClientServiceBinder.class.getSimpleName();
+
+ private MapClientService mService;
+
+ MapClientServiceBinder(MapClientService service) {
+ mService = service;
+ }
+
+ @Override
+ public void cleanup() {
+ mService = null;
+ }
+
+ @RequiresPermission(BLUETOOTH_CONNECT)
+ private MapClientService getService(AttributionSource source) {
+ MapClientService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !(getCallingUserHandle().isSystem()
+ || Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG))
+ || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
+ return null;
+ }
+ return service;
+ }
+
+ @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED})
+ private MapClientService getServiceAndEnforcePrivileged(AttributionSource source) {
+ MapClientService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !(getCallingUserHandle().isSystem()
+ || Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG))
+ || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
+ return null;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service;
+ }
+
+ @Override
+ public boolean connect(BluetoothDevice device, AttributionSource source) {
+ Log.v(TAG, "connect()");
+
+ MapClientService service = getServiceAndEnforcePrivileged(source);
+ if (service == null) {
+ return false;
+ }
+ return service.connect(device);
+ }
+
+ @Override
+ public boolean disconnect(BluetoothDevice device, AttributionSource source) {
+ Log.v(TAG, "disconnect()");
+
+ MapClientService service = getServiceAndEnforcePrivileged(source);
+ if (service == null) {
+ return false;
+ }
+ return service.disconnect(device);
+ }
+
+ @Override
+ public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
+ Log.v(TAG, "getConnectedDevices()");
+
+ MapClientService service = getServiceAndEnforcePrivileged(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getConnectedDevices();
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ int[] states, AttributionSource source) {
+ Log.v(TAG, "getDevicesMatchingConnectionStates()");
+
+ MapClientService service = getServiceAndEnforcePrivileged(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getDevicesMatchingConnectionStates(states);
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice device, AttributionSource source) {
+ Log.v(TAG, "getConnectionState()");
+
+ MapClientService service = getServiceAndEnforcePrivileged(source);
+ if (service == null) {
+ return STATE_DISCONNECTED;
+ }
+ return service.getConnectionState(device);
+ }
+
+ @Override
+ public boolean setConnectionPolicy(
+ BluetoothDevice device, int connectionPolicy, AttributionSource source) {
+ Log.v(TAG, "setConnectionPolicy()");
+
+ MapClientService service = getServiceAndEnforcePrivileged(source);
+ if (service == null) {
+ return false;
+ }
+ return service.setConnectionPolicy(device, connectionPolicy);
+ }
+
+ @Override
+ public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
+ Log.v(TAG, "getConnectionPolicy()");
+
+ MapClientService service = getServiceAndEnforcePrivileged(source);
+ if (service == null) {
+ return CONNECTION_POLICY_UNKNOWN;
+ }
+ return service.getConnectionPolicy(device);
+ }
+
+ @Override
+ public boolean sendMessage(
+ BluetoothDevice device,
+ Uri[] contacts,
+ String message,
+ PendingIntent sentIntent,
+ PendingIntent deliveredIntent,
+ AttributionSource source) {
+ Log.v(TAG, "sendMessage()");
+
+ MapClientService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ Log.d(TAG, "Checking Permission of sendMessage");
+ mService.enforceCallingOrSelfPermission(
+ Manifest.permission.SEND_SMS, "Need SEND_SMS permission");
+
+ return service.sendMessage(device, contacts, message, sentIntent, deliveredIntent);
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/mapclient/OWNERS b/android/app/src/com/android/bluetooth/mapclient/OWNERS
deleted file mode 100644
index b0b54fc3d2..0000000000
--- a/android/app/src/com/android/bluetooth/mapclient/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-include /OWNERS_automotive
-include /OWNERS_content
diff --git a/android/app/src/com/android/bluetooth/mcp/McpService.java b/android/app/src/com/android/bluetooth/mcp/McpService.java
index c0ba4f12bb..6f08be0061 100644
--- a/android/app/src/com/android/bluetooth/mcp/McpService.java
+++ b/android/app/src/com/android/bluetooth/mcp/McpService.java
@@ -17,12 +17,9 @@
package com.android.bluetooth.mcp;
-import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
import android.bluetooth.BluetoothDevice;
-import android.bluetooth.IBluetoothMcpServiceManager;
-import android.content.AttributionSource;
import android.content.Context;
import android.os.ParcelUuid;
import android.sysprop.BluetoothProperties;
@@ -88,7 +85,7 @@ public class McpService extends ProfileService {
@Override
protected IProfileServiceBinder initBinder() {
- return new BluetoothMcpServiceBinder(this);
+ return new McpServiceBinder(this);
}
@Override
@@ -198,41 +195,4 @@ public class McpService extends ProfileService {
int ccid, BluetoothDevice device, ParcelUuid charUuid, boolean doNotify) {
mGmcs.setNotificationSubscription(ccid, device, charUuid, doNotify);
}
-
- /** Binder object: must be a static class or memory leak may occur */
- static class BluetoothMcpServiceBinder extends IBluetoothMcpServiceManager.Stub
- implements IProfileServiceBinder {
- private McpService mService;
-
- BluetoothMcpServiceBinder(McpService svc) {
- mService = svc;
- }
-
- private McpService getService() {
- if (mService != null && mService.isAvailable()) {
- return mService;
- }
- Log.e(TAG, "getService() - Service requested, but not available!");
- return null;
- }
-
- @Override
- public void setDeviceAuthorized(
- BluetoothDevice device, boolean isAuthorized, AttributionSource source) {
- McpService service = getService();
- if (service == null) {
- return;
- }
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.setDeviceAuthorized(device, isAuthorized);
- }
-
- @Override
- public void cleanup() {
- if (mService != null) {
- mService.cleanup();
- }
- mService = null;
- }
- }
}
diff --git a/android/app/src/com/android/bluetooth/mcp/McpServiceBinder.java b/android/app/src/com/android/bluetooth/mcp/McpServiceBinder.java
new file mode 100644
index 0000000000..b22e87cadf
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/mcp/McpServiceBinder.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.mcp;
+
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.IBluetoothMcpServiceManager;
+import android.content.AttributionSource;
+import android.util.Log;
+
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+
+class McpServiceBinder extends IBluetoothMcpServiceManager.Stub implements IProfileServiceBinder {
+ private static final String TAG = McpServiceBinder.class.getSimpleName();
+
+ private McpService mService;
+
+ McpServiceBinder(McpService svc) {
+ mService = svc;
+ }
+
+ private McpService getService() {
+ if (mService != null && mService.isAvailable()) {
+ return mService;
+ }
+ Log.e(TAG, "getService() - Service requested, but not available!");
+ return null;
+ }
+
+ @Override
+ public void setDeviceAuthorized(
+ BluetoothDevice device, boolean isAuthorized, AttributionSource source) {
+ McpService service = getService();
+ if (service == null) {
+ return;
+ }
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.setDeviceAuthorized(device, isAuthorized);
+ }
+
+ @Override
+ public void cleanup() {
+ if (mService != null) {
+ mService.cleanup();
+ }
+ mService = null;
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/mcp/OWNERS b/android/app/src/com/android/bluetooth/mcp/OWNERS
deleted file mode 100644
index a7d77894ba..0000000000
--- a/android/app/src/com/android/bluetooth/mcp/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_leaudio
diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java
index 81c59f8ad2..d87bd420fe 100644
--- a/android/app/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java
+++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java
@@ -25,7 +25,6 @@ import android.util.Log;
import com.android.bluetooth.BluetoothMethodProxy;
import com.android.bluetooth.Utils;
-import com.android.bluetooth.flags.Flags;
import java.util.ArrayList;
@@ -82,10 +81,7 @@ public class BluetoothOppHandoverReceiver extends BroadcastReceiver {
if (device == null) {
return;
}
- String brEdrAddress =
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getBrEdrAddress(device)
- : device.getIdentityAddress();
+ String brEdrAddress = Utils.getBrEdrAddress(device);
Log.d(TAG, "Adding " + brEdrAddress + " to acceptlist");
BluetoothOppManager.getInstance(context).addToAcceptlist(brEdrAddress);
} else if (action.equals(Constants.ACTION_STOP_HANDOVER)) {
diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java
index 048c134848..73cba4e954 100644
--- a/android/app/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java
+++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java
@@ -248,6 +248,12 @@ public class BluetoothOppLauncherActivity extends Activity {
permittedUris,
false /* isHandover */,
true /* fromExternal */);
+ if (Flags.sendOppDevicePickerExtraIntent()) {
+ BluetoothOppUtility
+ .grantPermissionToNearbyComponent(
+ BluetoothOppLauncherActivity.this,
+ uris);
+ }
// Done getting file info..Launch device picker
// and finish this activity
launchDevicePicker();
@@ -322,6 +328,11 @@ public class BluetoothOppLauncherActivity extends Activity {
in1.putExtra(BluetoothDevicePicker.EXTRA_LAUNCH_PACKAGE, getPackageName());
in1.putExtra(
BluetoothDevicePicker.EXTRA_LAUNCH_CLASS, BluetoothOppReceiver.class.getName());
+ if (Flags.sendOppDevicePickerExtraIntent()) {
+ in1.putExtra(
+ BluetoothDevicePicker.EXTRA_DEVICE_PICKER_ORIGINAL_SEND_INTENT,
+ getIntent());
+ }
Log.v(TAG, "Launching " + BluetoothDevicePicker.ACTION_LAUNCH);
startActivity(in1);
}
@@ -555,6 +566,10 @@ public class BluetoothOppLauncherActivity extends Activity {
void sendFileInfo(String mimeType, String uriString, boolean isHandover, boolean fromExternal) {
BluetoothOppManager manager = BluetoothOppManager.getInstance(getApplicationContext());
try {
+ if (Flags.sendOppDevicePickerExtraIntent()) {
+ BluetoothOppUtility.grantPermissionToNearbyComponent(
+ this, List.of(Uri.parse(uriString)));
+ }
manager.saveSendingFileInfo(mimeType, uriString, isHandover, fromExternal);
launchDevicePicker();
finish();
diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppManager.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppManager.java
index 730c1e9ce2..c745f243d4 100644
--- a/android/app/src/com/android/bluetooth/opp/BluetoothOppManager.java
+++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppManager.java
@@ -54,7 +54,6 @@ import com.android.bluetooth.BluetoothStatsLog;
import com.android.bluetooth.R;
import com.android.bluetooth.Utils;
import com.android.bluetooth.content_profiles.ContentProfileErrorReportUtils;
-import com.android.bluetooth.flags.Flags;
import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
@@ -480,11 +479,7 @@ public class BluetoothOppManager {
}
values.put(BluetoothShare.MIMETYPE, contentType);
- values.put(
- BluetoothShare.DESTINATION,
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getBrEdrAddress(mRemoteDevice)
- : mRemoteDevice.getIdentityAddress());
+ values.put(BluetoothShare.DESTINATION, Utils.getBrEdrAddress(mRemoteDevice));
values.put(BluetoothShare.TIMESTAMP, ts);
if (mIsHandoverInitiated) {
values.put(
@@ -512,11 +507,7 @@ public class BluetoothOppManager {
ContentValues values = new ContentValues();
values.put(BluetoothShare.URI, mUri);
values.put(BluetoothShare.MIMETYPE, mTypeOfSingleFile);
- values.put(
- BluetoothShare.DESTINATION,
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getBrEdrAddress(mRemoteDevice)
- : mRemoteDevice.getIdentityAddress());
+ values.put(BluetoothShare.DESTINATION, Utils.getBrEdrAddress(mRemoteDevice));
if (mIsHandoverInitiated) {
values.put(
BluetoothShare.USER_CONFIRMATION,
diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppPreference.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppPreference.java
index 6164cb4f58..114adfe631 100644
--- a/android/app/src/com/android/bluetooth/opp/BluetoothOppPreference.java
+++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppPreference.java
@@ -32,7 +32,6 @@
package com.android.bluetooth.opp;
-import android.annotation.SuppressLint;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothUtils;
import android.content.Context;
@@ -41,7 +40,6 @@ import android.content.SharedPreferences.Editor;
import android.util.Log;
import com.android.bluetooth.Utils;
-import com.android.bluetooth.flags.Flags;
import java.util.HashMap;
@@ -87,11 +85,11 @@ public class BluetoothOppPreference {
}
private static String getChannelKey(BluetoothDevice remoteDevice, int uuid) {
- return getBrEdrAddress(remoteDevice) + "_" + Integer.toHexString(uuid);
+ return Utils.getBrEdrAddress(remoteDevice) + "_" + Integer.toHexString(uuid);
}
public String getName(BluetoothDevice remoteDevice) {
- String identityAddress = getBrEdrAddress(remoteDevice);
+ String identityAddress = Utils.getBrEdrAddress(remoteDevice);
if (identityAddress != null && identityAddress.equals("FF:FF:FF:00:00:00")) {
return "localhost";
}
@@ -113,7 +111,8 @@ public class BluetoothOppPreference {
Log.v(
TAG,
"getChannel for "
- + BluetoothUtils.toAnonymizedAddress(getBrEdrAddress(remoteDevice))
+ + BluetoothUtils.toAnonymizedAddress(
+ Utils.getBrEdrAddress(remoteDevice))
+ "_"
+ Integer.toHexString(uuid)
+ " as "
@@ -123,7 +122,7 @@ public class BluetoothOppPreference {
}
public void setName(BluetoothDevice remoteDevice, String name) {
- String brEdrAddress = getBrEdrAddress(remoteDevice);
+ String brEdrAddress = Utils.getBrEdrAddress(remoteDevice);
Log.v(
TAG,
"setName for " + BluetoothUtils.toAnonymizedAddress(brEdrAddress) + " to " + name);
@@ -139,7 +138,7 @@ public class BluetoothOppPreference {
Log.v(
TAG,
"setChannel for "
- + BluetoothUtils.toAnonymizedAddress(getBrEdrAddress(remoteDevice))
+ + BluetoothUtils.toAnonymizedAddress(Utils.getBrEdrAddress(remoteDevice))
+ "_"
+ Integer.toHexString(uuid)
+ " to "
@@ -163,7 +162,7 @@ public class BluetoothOppPreference {
public void removeName(BluetoothDevice remoteDevice) {
Editor ed = mNamePreference.edit();
- String key = getBrEdrAddress(remoteDevice);
+ String key = Utils.getBrEdrAddress(remoteDevice);
ed.remove(key);
ed.apply();
mNames.remove(key);
@@ -175,12 +174,4 @@ public class BluetoothOppPreference {
Log.d(TAG, "Dumping Channels: ");
Log.d(TAG, mChannels.toString());
}
-
- @SuppressLint("AndroidFrameworkRequiresPermission")
- private static String getBrEdrAddress(BluetoothDevice device) {
- if (Flags.identityAddressNullIfNotKnown()) {
- return Utils.getBrEdrAddress(device);
- }
- return device.getIdentityAddress();
- }
}
diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppReceiver.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppReceiver.java
index eb9b7f91c4..77dadd9a65 100644
--- a/android/app/src/com/android/bluetooth/opp/BluetoothOppReceiver.java
+++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppReceiver.java
@@ -52,7 +52,6 @@ import com.android.bluetooth.BluetoothStatsLog;
import com.android.bluetooth.R;
import com.android.bluetooth.Utils;
import com.android.bluetooth.content_profiles.ContentProfileErrorReportUtils;
-import com.android.bluetooth.flags.Flags;
/**
* Receives and handles: system broadcasts; Intents from other applications; Intents from
@@ -81,9 +80,7 @@ public class BluetoothOppReceiver extends BroadcastReceiver {
TAG,
"Received BT device selected intent, bt device: "
+ BluetoothUtils.toAnonymizedAddress(
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getBrEdrAddress(remoteDevice)
- : remoteDevice.getIdentityAddress()));
+ Utils.getBrEdrAddress(remoteDevice)));
// Insert transfer session record to database
mOppManager.startTransfer(remoteDevice);
diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java
index 2548b9e45c..f043cbcc53 100644
--- a/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java
+++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java
@@ -121,7 +121,7 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti
// Since ContentObserver is created with Handler, onChange() can be called
// even after the observer is unregistered.
- if (Flags.oppIgnoreContentObserverAfterServiceStop() && mObserver != this) {
+ if (mObserver != this) {
Log.d(TAG, "onChange() called after stop() is called.");
return;
}
@@ -1346,9 +1346,7 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti
+ socket
+ " \n :device :"
+ BluetoothUtils.toAnonymizedAddress(
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getBrEdrAddress(device, mAdapterService)
- : mAdapterService.getIdentityAddress(device.getAddress())));
+ Utils.getBrEdrAddress(device, mAdapterService)));
if (!mAcceptNewConnections) {
Log.d(TAG, " onConnect BluetoothSocket :" + socket + " rejected");
return false;
diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppTransfer.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppTransfer.java
index 1ff73d1b48..5e92f1e81e 100644
--- a/android/app/src/com/android/bluetooth/opp/BluetoothOppTransfer.java
+++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppTransfer.java
@@ -63,7 +63,6 @@ import com.android.bluetooth.BluetoothObexTransport;
import com.android.bluetooth.BluetoothStatsLog;
import com.android.bluetooth.Utils;
import com.android.bluetooth.content_profiles.ContentProfileErrorReportUtils;
-import com.android.bluetooth.flags.Flags;
import com.android.internal.annotations.VisibleForTesting;
import com.android.obex.ObexTransport;
@@ -116,7 +115,8 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
Log.e(
TAG,
"device : "
- + BluetoothUtils.toAnonymizedAddress(getBrEdrAddress(device))
+ + BluetoothUtils.toAnonymizedAddress(
+ Utils.getBrEdrAddress(device))
+ " mBatch :"
+ mBatch
+ " mCurrentShare :"
@@ -133,7 +133,8 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
Log.v(
TAG,
"Device :"
- + BluetoothUtils.toAnonymizedAddress(getBrEdrAddress(device))
+ + BluetoothUtils.toAnonymizedAddress(
+ Utils.getBrEdrAddress(device))
+ "- OPP device: "
+ mBatch.mDestination
+ " \n mCurrentShare.mConfirm == "
@@ -180,8 +181,8 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
3);
return;
}
- String deviceIdentityAddress = getBrEdrAddress(device);
- String transferDeviceIdentityAddress = getBrEdrAddress(mDevice);
+ String deviceIdentityAddress = Utils.getBrEdrAddress(device);
+ String transferDeviceIdentityAddress = Utils.getBrEdrAddress(mDevice);
if (deviceIdentityAddress == null
|| transferDeviceIdentityAddress == null
|| !deviceIdentityAddress.equalsIgnoreCase(
@@ -1008,11 +1009,4 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
}
}
}
-
- private static String getBrEdrAddress(BluetoothDevice device) {
- if (Flags.identityAddressNullIfNotKnown()) {
- return Utils.getBrEdrAddress(device);
- }
- return device.getIdentityAddress();
- }
}
diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppUtility.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppUtility.java
index d7b75bfde2..4e8892ab35 100644
--- a/android/app/src/com/android/bluetooth/opp/BluetoothOppUtility.java
+++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppUtility.java
@@ -38,6 +38,7 @@ import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothProtoEnums;
import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
@@ -50,6 +51,7 @@ import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.SystemProperties;
+import android.provider.Settings;
import android.util.EventLog;
import android.util.Log;
@@ -77,6 +79,9 @@ import java.util.concurrent.ConcurrentHashMap;
public class BluetoothOppUtility {
private static final String TAG = BluetoothOppUtility.class.getSimpleName();
+ // TODO(b/398120192): use API instead of a hardcode string.
+ private static final String NEARBY_SHARING_COMPONENT = "nearby_sharing_component";
+
/** Whether the device has the "nosdcard" characteristic, or null if not-yet-known. */
private static Boolean sNoSdCard = null;
@@ -572,4 +577,30 @@ public class BluetoothOppUtility {
NotificationManager nm = ctx.getSystemService(NotificationManager.class);
nm.cancel(BluetoothOppNotification.NOTIFICATION_ID_PROGRESS);
}
+
+ /** Grants uri read permission to nearby sharing component. */
+ static void grantPermissionToNearbyComponent(Context context, List<Uri> uris) {
+ String packageName = getNearbyComponentPackageName(context);
+ if (packageName == null) {
+ return;
+ }
+ for (Uri uri : uris) {
+ BluetoothMethodProxy.getInstance()
+ .grantUriPermission(
+ context, packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ }
+ }
+
+ private static String getNearbyComponentPackageName(Context context) {
+ String componentString =
+ Settings.Secure.getString(context.getContentResolver(), NEARBY_SHARING_COMPONENT);
+ if (componentString == null) {
+ return null;
+ }
+ ComponentName componentName = ComponentName.unflattenFromString(componentString);
+ if (componentName == null) {
+ return null;
+ }
+ return componentName.getPackageName();
+ }
}
diff --git a/android/app/src/com/android/bluetooth/opp/OWNERS b/android/app/src/com/android/bluetooth/opp/OWNERS
deleted file mode 100644
index 8f87191393..0000000000
--- a/android/app/src/com/android/bluetooth/opp/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_content \ No newline at end of file
diff --git a/android/app/src/com/android/bluetooth/pan/OWNERS b/android/app/src/com/android/bluetooth/pan/OWNERS
deleted file mode 100644
index 8f87191393..0000000000
--- a/android/app/src/com/android/bluetooth/pan/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_content \ No newline at end of file
diff --git a/android/app/src/com/android/bluetooth/pan/PanService.java b/android/app/src/com/android/bluetooth/pan/PanService.java
index 311e100b52..9196288928 100644
--- a/android/app/src/com/android/bluetooth/pan/PanService.java
+++ b/android/app/src/com/android/bluetooth/pan/PanService.java
@@ -17,8 +17,6 @@
package com.android.bluetooth.pan;
import static android.Manifest.permission.BLUETOOTH_CONNECT;
-import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
-import static android.Manifest.permission.TETHER_PRIVILEGED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
@@ -30,15 +28,12 @@ import static android.bluetooth.BluetoothUtils.logRemoteException;
import static java.util.Objects.requireNonNull;
import static java.util.Objects.requireNonNullElseGet;
-import android.annotation.RequiresPermission;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothPan.LocalPanRole;
import android.bluetooth.BluetoothPan.RemotePanRole;
import android.bluetooth.BluetoothProfile;
-import android.bluetooth.IBluetoothPan;
import android.bluetooth.IBluetoothPanCallback;
-import android.content.AttributionSource;
import android.content.Intent;
import android.content.res.Resources.NotFoundException;
import android.net.TetheringInterface;
@@ -55,12 +50,10 @@ import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.btservice.storage.DatabaseManager;
-import com.android.bluetooth.flags.Flags;
import com.android.internal.annotations.VisibleForTesting;
import com.android.modules.utils.HandlerExecutor;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -105,9 +98,7 @@ public class PanService extends ProfileService {
Log.e(TAG, "Error setting up tether interface: " + error);
for (BluetoothDevice device : mPanDevices.keySet()) {
mNativeInterface.disconnect(
- Flags.panUseIdentityAddress()
- ? Utils.getByteBrEdrAddress(mAdapterService, device)
- : Utils.getByteAddress(device));
+ Utils.getByteBrEdrAddress(mAdapterService, device));
}
mPanDevices.clear();
mIsTethering = false;
@@ -154,7 +145,7 @@ public class PanService extends ProfileService {
@Override
public IProfileServiceBinder initBinder() {
- return new BluetoothPanBinder(this);
+ return new PanServiceBinder(this);
}
public static synchronized PanService getPanService() {
@@ -218,9 +209,7 @@ public class PanService extends ProfileService {
case MESSAGE_CONNECT:
BluetoothDevice connectDevice = (BluetoothDevice) msg.obj;
if (!mNativeInterface.connect(
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getByteBrEdrAddress(mAdapterService, connectDevice)
- : mAdapterService.getByteIdentityAddress(connectDevice))) {
+ Utils.getByteBrEdrAddress(mAdapterService, connectDevice))) {
handlePanDeviceStateChange(
connectDevice,
null,
@@ -238,9 +227,7 @@ public class PanService extends ProfileService {
case MESSAGE_DISCONNECT:
BluetoothDevice disconnectDevice = (BluetoothDevice) msg.obj;
if (!mNativeInterface.disconnect(
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getByteBrEdrAddress(mAdapterService, disconnectDevice)
- : mAdapterService.getByteIdentityAddress(disconnectDevice))) {
+ Utils.getByteBrEdrAddress(mAdapterService, disconnectDevice))) {
handlePanDeviceStateChange(
disconnectDevice,
mPanIfName,
@@ -276,137 +263,6 @@ public class PanService extends ProfileService {
}
}
- /** Handlers for incoming service calls */
- @VisibleForTesting
- static class BluetoothPanBinder extends IBluetoothPan.Stub implements IProfileServiceBinder {
- private PanService mService;
-
- BluetoothPanBinder(PanService svc) {
- mService = svc;
- }
-
- @Override
- public void cleanup() {
- mService = null;
- }
-
- @RequiresPermission(BLUETOOTH_CONNECT)
- private PanService getService(AttributionSource source) {
- if (Utils.isInstrumentationTestMode()) {
- return mService;
- }
- if (!Utils.checkServiceAvailable(mService, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(mService, TAG)
- || !Utils.checkConnectPermissionForDataDelivery(mService, source, TAG)) {
- return null;
- }
- return mService;
- }
-
- @Override
- public boolean connect(BluetoothDevice device, AttributionSource source) {
- PanService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.connect(device);
- }
-
- @Override
- public boolean disconnect(BluetoothDevice device, AttributionSource source) {
- PanService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.disconnect(device);
- }
-
- @Override
- public boolean setConnectionPolicy(
- BluetoothDevice device, int connectionPolicy, AttributionSource source) {
- PanService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.setConnectionPolicy(device, connectionPolicy);
- }
-
- @Override
- public int getConnectionState(BluetoothDevice device, AttributionSource source) {
- PanService service = getService(source);
- if (service == null) {
- return BluetoothPan.STATE_DISCONNECTED;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getConnectionState(device);
- }
-
- @Override
- public boolean isTetheringOn(AttributionSource source) {
- // TODO(BT) have a variable marking the on/off state
- PanService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.isTetheringOn();
- }
-
- @Override
- public void setBluetoothTethering(
- IBluetoothPanCallback callback, int id, boolean value, AttributionSource source) {
- PanService service = getService(source);
- if (service == null) {
- return;
- }
-
- Log.d(
- TAG,
- "setBluetoothTethering:"
- + (" value=" + value)
- + (" pkgName= " + source.getPackageName())
- + (" mTetherOn= " + service.mTetherOn));
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.enforceCallingOrSelfPermission(TETHER_PRIVILEGED, null);
-
- service.setBluetoothTethering(callback, id, source.getUid(), value);
- }
-
- @Override
- public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
- PanService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getConnectedDevices();
- }
-
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(
- int[] states, AttributionSource source) {
- PanService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getDevicesMatchingConnectionStates(states);
- }
- }
-
public boolean connect(BluetoothDevice device) {
if (mUserManager.isGuestUser()) {
Log.w(TAG, "Guest user does not have the permission to change the WiFi network");
@@ -641,10 +497,7 @@ public class PanService extends ProfileService {
"handlePanDeviceStateChange BT tethering is off/Local role"
+ " is PANU drop the connection");
mPanDevices.remove(device);
- mNativeInterface.disconnect(
- Flags.panUseIdentityAddress()
- ? Utils.getByteBrEdrAddress(mAdapterService, device)
- : Utils.getByteAddress(device));
+ mNativeInterface.disconnect(Utils.getByteBrEdrAddress(mAdapterService, device));
return;
}
Log.d(TAG, "handlePanDeviceStateChange LOCAL_NAP_ROLE:REMOTE_PANU_ROLE");
diff --git a/android/app/src/com/android/bluetooth/pan/PanServiceBinder.java b/android/app/src/com/android/bluetooth/pan/PanServiceBinder.java
new file mode 100644
index 0000000000..e3baae21dc
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/pan/PanServiceBinder.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.pan;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.Manifest.permission.TETHER_PRIVILEGED;
+
+import android.annotation.RequiresPermission;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothPan;
+import android.bluetooth.IBluetoothPan;
+import android.bluetooth.IBluetoothPanCallback;
+import android.content.AttributionSource;
+import android.util.Log;
+
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+
+import java.util.Collections;
+import java.util.List;
+
+/** Handlers for incoming service calls */
+class PanServiceBinder extends IBluetoothPan.Stub implements IProfileServiceBinder {
+ private static final String TAG = PanServiceBinder.class.getSimpleName();
+
+ private PanService mService;
+
+ PanServiceBinder(PanService svc) {
+ mService = svc;
+ }
+
+ @Override
+ public void cleanup() {
+ mService = null;
+ }
+
+ @RequiresPermission(BLUETOOTH_CONNECT)
+ private PanService getService(AttributionSource source) {
+ if (Utils.isInstrumentationTestMode()) {
+ return mService;
+ }
+ if (!Utils.checkServiceAvailable(mService, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(mService, TAG)
+ || !Utils.checkConnectPermissionForDataDelivery(mService, source, TAG)) {
+ return null;
+ }
+ return mService;
+ }
+
+ @Override
+ public boolean connect(BluetoothDevice device, AttributionSource source) {
+ PanService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.connect(device);
+ }
+
+ @Override
+ public boolean disconnect(BluetoothDevice device, AttributionSource source) {
+ PanService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.disconnect(device);
+ }
+
+ @Override
+ public boolean setConnectionPolicy(
+ BluetoothDevice device, int connectionPolicy, AttributionSource source) {
+ PanService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.setConnectionPolicy(device, connectionPolicy);
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice device, AttributionSource source) {
+ PanService service = getService(source);
+ if (service == null) {
+ return BluetoothPan.STATE_DISCONNECTED;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getConnectionState(device);
+ }
+
+ @Override
+ public boolean isTetheringOn(AttributionSource source) {
+ // TODO(BT) have a variable marking the on/off state
+ PanService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.isTetheringOn();
+ }
+
+ @Override
+ public void setBluetoothTethering(
+ IBluetoothPanCallback callback, int id, boolean value, AttributionSource source) {
+ PanService service = getService(source);
+ if (service == null) {
+ return;
+ }
+
+ Log.d(
+ TAG,
+ "setBluetoothTethering:"
+ + (" value=" + value)
+ + (" pkgName= " + source.getPackageName())
+ + (" mTetherOn= " + service.isTetheringOn()));
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.enforceCallingOrSelfPermission(TETHER_PRIVILEGED, null);
+
+ service.setBluetoothTethering(callback, id, source.getUid(), value);
+ }
+
+ @Override
+ public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
+ PanService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getConnectedDevices();
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ int[] states, AttributionSource source) {
+ PanService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getDevicesMatchingConnectionStates(states);
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapActivity.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapActivity.java
index 7223516e88..18fff92890 100644
--- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapActivity.java
+++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapActivity.java
@@ -5,7 +5,7 @@
* 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
+ * 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,
diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapAuthenticator.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapAuthenticator.java
index 55419908eb..2e788d424a 100644
--- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapAuthenticator.java
+++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapAuthenticator.java
@@ -5,7 +5,7 @@
* 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
+ * 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,
diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapConfig.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapConfig.java
index 6fec2895e6..391d759065 100644
--- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapConfig.java
+++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapConfig.java
@@ -5,7 +5,7 @@
* 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
+ * 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,
diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapObexServer.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapObexServer.java
index 88f7023b03..c5bb01f426 100644
--- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapObexServer.java
+++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapObexServer.java
@@ -5,7 +5,7 @@
* 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
+ * 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,
diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java
index 00194f5d78..2d67fc9947 100644
--- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java
+++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java
@@ -5,7 +5,7 @@
* 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
+ * 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,
@@ -17,7 +17,6 @@
package com.android.bluetooth.pbap;
import static android.Manifest.permission.BLUETOOTH_CONNECT;
-import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
import static android.bluetooth.BluetoothDevice.ACCESS_ALLOWED;
import static android.bluetooth.BluetoothDevice.ACCESS_REJECTED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
@@ -28,19 +27,15 @@ import static com.android.bluetooth.Utils.joinUninterruptibly;
import static java.util.Objects.requireNonNull;
-import android.annotation.RequiresPermission;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
-import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothProtoEnums;
import android.bluetooth.BluetoothSocket;
import android.bluetooth.BluetoothUtils;
-import android.bluetooth.IBluetoothPbap;
-import android.content.AttributionSource;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -75,7 +70,6 @@ import com.android.bluetooth.util.DevicePolicyUtils;
import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -734,7 +728,7 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect
@Override
protected IProfileServiceBinder initBinder() {
- return new PbapBinder(this);
+ return new BluetoothPbapServiceBinder(this);
}
@Override
@@ -775,97 +769,6 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect
sBluetoothPbapService = instance;
}
- @VisibleForTesting
- static class PbapBinder extends IBluetoothPbap.Stub implements IProfileServiceBinder {
- private BluetoothPbapService mService;
-
- PbapBinder(BluetoothPbapService service) {
- Log.v(TAG, "PbapBinder()");
- mService = service;
- }
-
- @Override
- public void cleanup() {
- mService = null;
- }
-
- @RequiresPermission(BLUETOOTH_CONNECT)
- private BluetoothPbapService getService(AttributionSource source) {
- // Cache mService because it can change while getService is called
- BluetoothPbapService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
-
- return service;
- }
-
- @Override
- public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
- Log.d(TAG, "getConnectedDevices");
- BluetoothPbapService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
- return service.getConnectedDevices();
- }
-
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(
- int[] states, AttributionSource source) {
- Log.d(TAG, "getDevicesMatchingConnectionStates");
- BluetoothPbapService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
- return service.getDevicesMatchingConnectionStates(states);
- }
-
- @Override
- public int getConnectionState(BluetoothDevice device, AttributionSource source) {
- Log.d(TAG, "getConnectionState: " + device);
- BluetoothPbapService service = getService(source);
- if (service == null) {
- return BluetoothAdapter.STATE_DISCONNECTED;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getConnectionState(device);
- }
-
- @Override
- public boolean setConnectionPolicy(
- BluetoothDevice device, int connectionPolicy, AttributionSource source) {
- Log.d(TAG, "setConnectionPolicy for device=" + device + " policy=" + connectionPolicy);
- BluetoothPbapService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.setConnectionPolicy(device, connectionPolicy);
- }
-
- @Override
- public void disconnect(BluetoothDevice device, AttributionSource source) {
- Log.d(TAG, "disconnect");
- BluetoothPbapService service = getService(source);
- if (service == null) {
- return;
- }
- service.disconnect(device);
- }
- }
-
@Override
public boolean onConnect(BluetoothDevice remoteDevice, BluetoothSocket socket) {
if (remoteDevice == null || socket == null) {
diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapServiceBinder.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapServiceBinder.java
new file mode 100644
index 0000000000..67ad07169a
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapServiceBinder.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.pbap;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+
+import android.annotation.RequiresPermission;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.IBluetoothPbap;
+import android.content.AttributionSource;
+import android.util.Log;
+
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+
+import java.util.Collections;
+import java.util.List;
+
+class BluetoothPbapServiceBinder extends IBluetoothPbap.Stub implements IProfileServiceBinder {
+ private static final String TAG = BluetoothPbapServiceBinder.class.getSimpleName();
+
+ private BluetoothPbapService mService;
+
+ BluetoothPbapServiceBinder(BluetoothPbapService service) {
+ mService = service;
+ }
+
+ @Override
+ public void cleanup() {
+ mService = null;
+ }
+
+ @RequiresPermission(BLUETOOTH_CONNECT)
+ private BluetoothPbapService getService(AttributionSource source) {
+ BluetoothPbapService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
+ || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
+ return null;
+ }
+
+ return service;
+ }
+
+ @Override
+ public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
+ Log.d(TAG, "getConnectedDevices");
+ BluetoothPbapService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getConnectedDevices();
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ int[] states, AttributionSource source) {
+ Log.d(TAG, "getDevicesMatchingConnectionStates");
+ BluetoothPbapService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getDevicesMatchingConnectionStates(states);
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice device, AttributionSource source) {
+ Log.d(TAG, "getConnectionState: " + device);
+ BluetoothPbapService service = getService(source);
+ if (service == null) {
+ return BluetoothAdapter.STATE_DISCONNECTED;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getConnectionState(device);
+ }
+
+ @Override
+ public boolean setConnectionPolicy(
+ BluetoothDevice device, int connectionPolicy, AttributionSource source) {
+ Log.d(TAG, "setConnectionPolicy for device=" + device + " policy=" + connectionPolicy);
+ BluetoothPbapService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.setConnectionPolicy(device, connectionPolicy);
+ }
+
+ @Override
+ public void disconnect(BluetoothDevice device, AttributionSource source) {
+ Log.d(TAG, "disconnect");
+ BluetoothPbapService service = getService(source);
+ if (service == null) {
+ return;
+ }
+ service.disconnect(device);
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManager.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManager.java
index db427991a2..c63ec28105 100644
--- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManager.java
+++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManager.java
@@ -5,7 +5,7 @@
* 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
+ * 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,
diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapUtils.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapUtils.java
index e70706f84d..75a1b3d9f8 100644
--- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapUtils.java
+++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapUtils.java
@@ -5,7 +5,7 @@
* 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
+ * 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,
diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java
index 5fa66a785c..c3b08a2e89 100644
--- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java
+++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapVcardManager.java
@@ -5,7 +5,7 @@
* 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
+ * 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,
diff --git a/android/app/src/com/android/bluetooth/pbap/OWNERS b/android/app/src/com/android/bluetooth/pbap/OWNERS
deleted file mode 100644
index 8f87191393..0000000000
--- a/android/app/src/com/android/bluetooth/pbap/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_content \ No newline at end of file
diff --git a/android/app/src/com/android/bluetooth/pbapclient/OWNERS b/android/app/src/com/android/bluetooth/pbapclient/OWNERS
deleted file mode 100644
index b0b54fc3d2..0000000000
--- a/android/app/src/com/android/bluetooth/pbapclient/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-include /OWNERS_automotive
-include /OWNERS_content
diff --git a/android/app/src/com/android/bluetooth/pbapclient/PbapClientService.java b/android/app/src/com/android/bluetooth/pbapclient/PbapClientService.java
index c83e856a72..9b75de98f0 100644
--- a/android/app/src/com/android/bluetooth/pbapclient/PbapClientService.java
+++ b/android/app/src/com/android/bluetooth/pbapclient/PbapClientService.java
@@ -173,7 +173,7 @@ public class PbapClientService extends ProfileService {
@Override
public IProfileServiceBinder initBinder() {
- return new PbapClientBinder(this);
+ return new PbapClientServiceBinder(this);
}
@Override
diff --git a/android/app/src/com/android/bluetooth/pbapclient/PbapClientBinder.java b/android/app/src/com/android/bluetooth/pbapclient/PbapClientServiceBinder.java
index f3bcd1e7b5..5a45896f02 100644
--- a/android/app/src/com/android/bluetooth/pbapclient/PbapClientBinder.java
+++ b/android/app/src/com/android/bluetooth/pbapclient/PbapClientServiceBinder.java
@@ -35,12 +35,12 @@ import java.util.Collections;
import java.util.List;
/** Handler for incoming service calls destined for PBAP Client */
-class PbapClientBinder extends IBluetoothPbapClient.Stub implements IProfileServiceBinder {
- private static final String TAG = PbapClientBinder.class.getSimpleName();
+class PbapClientServiceBinder extends IBluetoothPbapClient.Stub implements IProfileServiceBinder {
+ private static final String TAG = PbapClientServiceBinder.class.getSimpleName();
private PbapClientService mService;
- PbapClientBinder(PbapClientService service) {
+ PbapClientServiceBinder(PbapClientService service) {
mService = service;
}
diff --git a/android/app/src/com/android/bluetooth/sap/OWNERS b/android/app/src/com/android/bluetooth/sap/OWNERS
deleted file mode 100644
index 8f87191393..0000000000
--- a/android/app/src/com/android/bluetooth/sap/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_content \ No newline at end of file
diff --git a/android/app/src/com/android/bluetooth/sap/SapService.java b/android/app/src/com/android/bluetooth/sap/SapService.java
index c8bda8e046..54391d24e3 100644
--- a/android/app/src/com/android/bluetooth/sap/SapService.java
+++ b/android/app/src/com/android/bluetooth/sap/SapService.java
@@ -20,7 +20,6 @@ import static android.Manifest.permission.BLUETOOTH_CONNECT;
import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
@@ -37,8 +36,6 @@ import android.bluetooth.BluetoothSap;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.bluetooth.BluetoothUuid;
-import android.bluetooth.IBluetoothSap;
-import android.content.AttributionSource;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -61,7 +58,6 @@ import com.android.internal.annotations.VisibleForTesting;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
public class SapService extends ProfileService implements AdapterService.BluetoothStateCallback {
@@ -672,7 +668,7 @@ public class SapService extends ProfileService implements AdapterService.Bluetoo
@Override
protected IProfileServiceBinder initBinder() {
- return new SapBinder(this);
+ return new SapServiceBinder(this);
}
@Override
@@ -881,145 +877,4 @@ public class SapService extends ProfileService implements AdapterService.Bluetoo
mSessionStatusHandler.sendEmptyMessage(MSG_SERVERSESSION_CLOSE);
}
}
-
- // Binder object: Must be static class or memory leak may occur
-
- /**
- * This class implements the IBluetoothSap interface - or actually it validates the
- * preconditions for calling the actual functionality in the SapService, and calls it.
- */
- private static class SapBinder extends IBluetoothSap.Stub implements IProfileServiceBinder {
- private SapService mService;
-
- SapBinder(SapService service) {
- Log.v(TAG, "SapBinder()");
- mService = service;
- }
-
- @Override
- public void cleanup() {
- mService = null;
- }
-
- @RequiresPermission(BLUETOOTH_CONNECT)
- private SapService getService(AttributionSource source) {
- // Cache mService because it can change while getService is called
- SapService service = mService;
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
-
- return service;
- }
-
- @Override
- public int getState(AttributionSource source) {
- Log.v(TAG, "getState()");
-
- SapService service = getService(source);
- if (service == null) {
- return BluetoothSap.STATE_DISCONNECTED;
- }
-
- return service.getState();
- }
-
- @Override
- public BluetoothDevice getClient(AttributionSource source) {
- Log.v(TAG, "getClient()");
-
- SapService service = getService(source);
- if (service == null) {
- return null;
- }
-
- Log.v(TAG, "getClient() - returning " + service.getRemoteDevice());
- return service.getRemoteDevice();
- }
-
- @Override
- public boolean isConnected(BluetoothDevice device, AttributionSource source) {
- Log.v(TAG, "isConnected()");
-
- SapService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.getConnectionState(device) == STATE_CONNECTED;
- }
-
- @Override
- public boolean disconnect(BluetoothDevice device, AttributionSource source) {
- Log.v(TAG, "disconnect()");
-
- SapService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.disconnect(device);
- }
-
- @Override
- public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
- Log.v(TAG, "getConnectedDevices()");
-
- SapService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- return service.getConnectedDevices();
- }
-
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(
- int[] states, AttributionSource source) {
- Log.v(TAG, "getDevicesMatchingConnectionStates()");
-
- SapService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- return service.getDevicesMatchingConnectionStates(states);
- }
-
- @Override
- public int getConnectionState(BluetoothDevice device, AttributionSource source) {
- Log.v(TAG, "getConnectionState()");
-
- SapService service = getService(source);
- if (service == null) {
- return STATE_DISCONNECTED;
- }
-
- return service.getConnectionState(device);
- }
-
- @Override
- public boolean setConnectionPolicy(
- BluetoothDevice device, int connectionPolicy, AttributionSource source) {
- SapService service = getService(source);
- if (service == null) {
- return false;
- }
-
- return service.setConnectionPolicy(device, connectionPolicy);
- }
-
- @Override
- public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
- SapService service = getService(source);
- if (service == null) {
- return CONNECTION_POLICY_UNKNOWN;
- }
-
- return service.getConnectionPolicy(device);
- }
- }
}
diff --git a/android/app/src/com/android/bluetooth/sap/SapServiceBinder.java b/android/app/src/com/android/bluetooth/sap/SapServiceBinder.java
new file mode 100644
index 0000000000..4c8a96901a
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/sap/SapServiceBinder.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.sap;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
+import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+
+import android.annotation.RequiresPermission;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothSap;
+import android.bluetooth.IBluetoothSap;
+import android.content.AttributionSource;
+import android.util.Log;
+
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * This class implements the IBluetoothSap interface - or actually it validates the preconditions
+ * for calling the actual functionality in the SapService, and calls it.
+ */
+class SapServiceBinder extends IBluetoothSap.Stub implements IProfileServiceBinder {
+ private static final String TAG = SapServiceBinder.class.getSimpleName();
+
+ private SapService mService;
+
+ SapServiceBinder(SapService service) {
+ mService = service;
+ }
+
+ @Override
+ public void cleanup() {
+ mService = null;
+ }
+
+ @RequiresPermission(BLUETOOTH_CONNECT)
+ private SapService getService(AttributionSource source) {
+ SapService service = mService;
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
+ || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
+ return null;
+ }
+
+ return service;
+ }
+
+ @Override
+ public int getState(AttributionSource source) {
+ Log.v(TAG, "getState()");
+
+ SapService service = getService(source);
+ if (service == null) {
+ return BluetoothSap.STATE_DISCONNECTED;
+ }
+ return service.getState();
+ }
+
+ @Override
+ public BluetoothDevice getClient(AttributionSource source) {
+ Log.v(TAG, "getClient()");
+
+ SapService service = getService(source);
+ if (service == null) {
+ return null;
+ }
+
+ Log.v(TAG, "getClient() - returning " + service.getRemoteDevice());
+ return service.getRemoteDevice();
+ }
+
+ @Override
+ public boolean isConnected(BluetoothDevice device, AttributionSource source) {
+ Log.v(TAG, "isConnected()");
+
+ SapService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.getConnectionState(device) == STATE_CONNECTED;
+ }
+
+ @Override
+ public boolean disconnect(BluetoothDevice device, AttributionSource source) {
+ Log.v(TAG, "disconnect()");
+
+ SapService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.disconnect(device);
+ }
+
+ @Override
+ public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
+ Log.v(TAG, "getConnectedDevices()");
+
+ SapService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getConnectedDevices();
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ int[] states, AttributionSource source) {
+ Log.v(TAG, "getDevicesMatchingConnectionStates()");
+
+ SapService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ return service.getDevicesMatchingConnectionStates(states);
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice device, AttributionSource source) {
+ Log.v(TAG, "getConnectionState()");
+
+ SapService service = getService(source);
+ if (service == null) {
+ return STATE_DISCONNECTED;
+ }
+ return service.getConnectionState(device);
+ }
+
+ @Override
+ public boolean setConnectionPolicy(
+ BluetoothDevice device, int connectionPolicy, AttributionSource source) {
+ SapService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+ return service.setConnectionPolicy(device, connectionPolicy);
+ }
+
+ @Override
+ public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
+ SapService service = getService(source);
+ if (service == null) {
+ return CONNECTION_POLICY_UNKNOWN;
+ }
+ return service.getConnectionPolicy(device);
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/sdp/SdpManager.java b/android/app/src/com/android/bluetooth/sdp/SdpManager.java
index 3a316f8457..de6193aeb2 100644
--- a/android/app/src/com/android/bluetooth/sdp/SdpManager.java
+++ b/android/app/src/com/android/bluetooth/sdp/SdpManager.java
@@ -35,7 +35,6 @@ import android.util.Log;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AbstractionLayer;
import com.android.bluetooth.btservice.AdapterService;
-import com.android.bluetooth.flags.Flags;
import com.android.internal.annotations.GuardedBy;
import java.util.ArrayList;
@@ -143,16 +142,10 @@ public class SdpManager {
SdpSearchInstance getSearchInstance(byte[] address, byte[] uuidBytes) {
String addressString = Utils.getAddressStringFromByte(address);
- addressString =
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getBrEdrAddress(addressString, mAdapterService)
- : mAdapterService.getIdentityAddress(addressString);
+ addressString = Utils.getBrEdrAddress(addressString, mAdapterService);
ParcelUuid uuid = Utils.byteArrayToUuid(uuidBytes)[0];
for (SdpSearchInstance inst : mList) {
- String instAddressString =
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getBrEdrAddress(inst.getDevice(), mAdapterService)
- : mAdapterService.getIdentityAddress(inst.getDevice().getAddress());
+ String instAddressString = Utils.getBrEdrAddress(inst.getDevice(), mAdapterService);
if (instAddressString.equals(addressString) && inst.getUuid().equals(uuid)) {
return inst;
}
@@ -161,15 +154,9 @@ public class SdpManager {
}
boolean isSearching(BluetoothDevice device, ParcelUuid uuid) {
- String addressString =
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getBrEdrAddress(device, mAdapterService)
- : mAdapterService.getIdentityAddress(device.getAddress());
+ String addressString = Utils.getBrEdrAddress(device, mAdapterService);
for (SdpSearchInstance inst : mList) {
- String instAddressString =
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getBrEdrAddress(inst.getDevice(), mAdapterService)
- : mAdapterService.getIdentityAddress(inst.getDevice().getAddress());
+ String instAddressString = Utils.getBrEdrAddress(inst.getDevice(), mAdapterService);
if (instAddressString != null
&& addressString != null
&& instAddressString.equals(addressString)
@@ -473,9 +460,7 @@ public class SdpManager {
inst.startSearch(); // Trigger timeout message
mNativeInterface.sdpSearch(
- Flags.identityAddressNullIfNotKnown()
- ? Utils.getByteBrEdrAddress(inst.getDevice())
- : mAdapterService.getByteIdentityAddress(inst.getDevice()),
+ Utils.getByteBrEdrAddress(inst.getDevice()),
Utils.uuidToByteArray(inst.getUuid()));
} else { // Else queue is empty.
Log.d(
diff --git a/android/app/src/com/android/bluetooth/tbs/TbsService.java b/android/app/src/com/android/bluetooth/tbs/TbsService.java
index ebd25f8229..3bb2fa45e7 100644
--- a/android/app/src/com/android/bluetooth/tbs/TbsService.java
+++ b/android/app/src/com/android/bluetooth/tbs/TbsService.java
@@ -17,19 +17,13 @@
package com.android.bluetooth.tbs;
-import static android.Manifest.permission.BLUETOOTH_CONNECT;
-import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
import static java.util.Objects.requireNonNull;
-import android.annotation.RequiresPermission;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeCall;
-import android.bluetooth.IBluetoothLeCallControl;
import android.bluetooth.IBluetoothLeCallControlCallback;
-import android.content.AttributionSource;
-import android.os.ParcelUuid;
import android.os.RemoteException;
import android.sysprop.BluetoothProperties;
import android.util.Log;
@@ -38,7 +32,6 @@ import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.le_audio.LeAudioService;
-import com.android.internal.annotations.VisibleForTesting;
import java.util.HashMap;
import java.util.List;
@@ -68,7 +61,7 @@ public class TbsService extends ProfileService {
@Override
protected IProfileServiceBinder initBinder() {
- return new TbsServerBinder(this);
+ return new TbsServiceBinder(this);
}
@Override
@@ -206,105 +199,6 @@ public class TbsService extends ProfileService {
mTbsGeneric.clearInbandRingtoneSupport(device);
}
- /** Binder object: must be a static class or memory leak may occur */
- @VisibleForTesting
- static class TbsServerBinder extends IBluetoothLeCallControl.Stub
- implements IProfileServiceBinder {
- private TbsService mService;
-
- TbsServerBinder(TbsService service) {
- mService = service;
- }
-
- @Override
- public void cleanup() {
- mService = null;
- }
-
- @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED})
- private TbsService getService(AttributionSource source) {
- // Cache mService because it can change while getService is called
- TbsService service = mService;
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service;
- }
-
- @Override
- public void registerBearer(
- String token,
- IBluetoothLeCallControlCallback callback,
- String uci,
- List<String> uriSchemes,
- int capabilities,
- String providerName,
- int technology,
- AttributionSource source) {
- TbsService service = getService(source);
- if (service != null) {
- service.registerBearer(
- token, callback, uci, uriSchemes, capabilities, providerName, technology);
- }
- }
-
- @Override
- public void unregisterBearer(String token, AttributionSource source) {
- TbsService service = getService(source);
- if (service != null) {
- service.unregisterBearer(token);
- }
- }
-
- @Override
- public void requestResult(int ccid, int requestId, int result, AttributionSource source) {
- TbsService service = getService(source);
- if (service != null) {
- service.requestResult(ccid, requestId, result);
- }
- }
-
- @Override
- public void callAdded(int ccid, BluetoothLeCall call, AttributionSource source) {
- TbsService service = getService(source);
- if (service != null) {
- service.callAdded(ccid, call);
- }
- }
-
- @Override
- public void callRemoved(int ccid, ParcelUuid callId, int reason, AttributionSource source) {
- TbsService service = getService(source);
- if (service != null) {
- service.callRemoved(ccid, callId.getUuid(), reason);
- }
- }
-
- @Override
- public void callStateChanged(
- int ccid, ParcelUuid callId, int state, AttributionSource source) {
- TbsService service = getService(source);
- if (service != null) {
- service.callStateChanged(ccid, callId.getUuid(), state);
- }
- }
-
- @Override
- public void currentCallsList(
- int ccid, List<BluetoothLeCall> calls, AttributionSource source) {
- TbsService service = getService(source);
- if (service != null) {
- service.currentCallsList(ccid, calls);
- }
- }
- }
-
- @VisibleForTesting
void registerBearer(
String token,
IBluetoothLeCallControlCallback callback,
@@ -335,42 +229,36 @@ public class TbsService extends ProfileService {
Log.d(TAG, "registerBearer: token=" + token + " success=" + success);
}
- @VisibleForTesting
void unregisterBearer(String token) {
Log.d(TAG, "unregisterBearer: token=" + token);
mTbsGeneric.removeBearer(token);
}
- @VisibleForTesting
public void requestResult(int ccid, int requestId, int result) {
Log.d(TAG, "requestResult: ccid=" + ccid + " requestId=" + requestId + " result=" + result);
mTbsGeneric.requestResult(ccid, requestId, result);
}
- @VisibleForTesting
void callAdded(int ccid, BluetoothLeCall call) {
Log.d(TAG, "callAdded: ccid=" + ccid + " call=" + call);
mTbsGeneric.callAdded(ccid, call);
}
- @VisibleForTesting
void callRemoved(int ccid, UUID callId, int reason) {
Log.d(TAG, "callRemoved: ccid=" + ccid + " callId=" + callId + " reason=" + reason);
mTbsGeneric.callRemoved(ccid, callId, reason);
}
- @VisibleForTesting
void callStateChanged(int ccid, UUID callId, int state) {
Log.d(TAG, "callStateChanged: ccid=" + ccid + " callId=" + callId + " state=" + state);
mTbsGeneric.callStateChanged(ccid, callId, state);
}
- @VisibleForTesting
void currentCallsList(int ccid, List<BluetoothLeCall> calls) {
Log.d(TAG, "currentCallsList: ccid=" + ccid + " calls=" + calls);
diff --git a/android/app/src/com/android/bluetooth/tbs/TbsServiceBinder.java b/android/app/src/com/android/bluetooth/tbs/TbsServiceBinder.java
new file mode 100644
index 0000000000..88a1a3435c
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/tbs/TbsServiceBinder.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.tbs;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+
+import android.annotation.RequiresPermission;
+import android.bluetooth.BluetoothLeCall;
+import android.bluetooth.IBluetoothLeCallControl;
+import android.bluetooth.IBluetoothLeCallControlCallback;
+import android.content.AttributionSource;
+import android.os.ParcelUuid;
+
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+
+import java.util.List;
+
+class TbsServiceBinder extends IBluetoothLeCallControl.Stub implements IProfileServiceBinder {
+ private static final String TAG = TbsServiceBinder.class.getSimpleName();
+
+ private TbsService mService;
+
+ TbsServiceBinder(TbsService service) {
+ mService = service;
+ }
+
+ @Override
+ public void cleanup() {
+ mService = null;
+ }
+
+ @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED})
+ private TbsService getService(AttributionSource source) {
+ TbsService service = mService;
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
+ || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
+ return null;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service;
+ }
+
+ @Override
+ public void registerBearer(
+ String token,
+ IBluetoothLeCallControlCallback callback,
+ String uci,
+ List<String> uriSchemes,
+ int capabilities,
+ String providerName,
+ int technology,
+ AttributionSource source) {
+ TbsService service = getService(source);
+ if (service != null) {
+ service.registerBearer(
+ token, callback, uci, uriSchemes, capabilities, providerName, technology);
+ }
+ }
+
+ @Override
+ public void unregisterBearer(String token, AttributionSource source) {
+ TbsService service = getService(source);
+ if (service != null) {
+ service.unregisterBearer(token);
+ }
+ }
+
+ @Override
+ public void requestResult(int ccid, int requestId, int result, AttributionSource source) {
+ TbsService service = getService(source);
+ if (service != null) {
+ service.requestResult(ccid, requestId, result);
+ }
+ }
+
+ @Override
+ public void callAdded(int ccid, BluetoothLeCall call, AttributionSource source) {
+ TbsService service = getService(source);
+ if (service != null) {
+ service.callAdded(ccid, call);
+ }
+ }
+
+ @Override
+ public void callRemoved(int ccid, ParcelUuid callId, int reason, AttributionSource source) {
+ TbsService service = getService(source);
+ if (service != null) {
+ service.callRemoved(ccid, callId.getUuid(), reason);
+ }
+ }
+
+ @Override
+ public void callStateChanged(int ccid, ParcelUuid callId, int state, AttributionSource source) {
+ TbsService service = getService(source);
+ if (service != null) {
+ service.callStateChanged(ccid, callId.getUuid(), state);
+ }
+ }
+
+ @Override
+ public void currentCallsList(int ccid, List<BluetoothLeCall> calls, AttributionSource source) {
+ TbsService service = getService(source);
+ if (service != null) {
+ service.currentCallsList(ccid, calls);
+ }
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/vc/OWNERS b/android/app/src/com/android/bluetooth/vc/OWNERS
deleted file mode 100644
index a7d77894ba..0000000000
--- a/android/app/src/com/android/bluetooth/vc/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_leaudio
diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java
index 628a36b6e8..b21d4e19b3 100644
--- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java
+++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java
@@ -17,8 +17,6 @@
package com.android.bluetooth.vc;
-import static android.Manifest.permission.BLUETOOTH_CONNECT;
-import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
import static android.bluetooth.BluetoothDevice.BOND_BONDED;
import static android.bluetooth.BluetoothDevice.BOND_NONE;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
@@ -36,19 +34,14 @@ import static com.android.bluetooth.flags.Flags.vcpDeviceVolumeApiImprovements;
import static java.util.Objects.requireNonNull;
import static java.util.Objects.requireNonNullElseGet;
-import android.annotation.RequiresPermission;
import android.bluetooth.AudioInputControl.AudioInputStatus;
import android.bluetooth.AudioInputControl.AudioInputType;
import android.bluetooth.AudioInputControl.GainMode;
import android.bluetooth.AudioInputControl.Mute;
-import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
-import android.bluetooth.IAudioInputCallback;
-import android.bluetooth.IBluetoothVolumeControl;
import android.bluetooth.IBluetoothVolumeControlCallback;
-import android.content.AttributionSource;
import android.media.AudioManager;
import android.os.Handler;
import android.os.HandlerThread;
@@ -70,22 +63,13 @@ import com.android.bluetooth.le_audio.LeAudioService;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import libcore.util.SneakyThrow;
-
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executors;
-import java.util.concurrent.FutureTask;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.function.Function;
public class VolumeControlService extends ProfileService {
private static final String TAG = VolumeControlService.class.getSimpleName();
@@ -166,7 +150,7 @@ public class VolumeControlService extends ProfileService {
@Override
protected IProfileServiceBinder initBinder() {
- return new BluetoothVolumeControlBinder(this);
+ return new VolumeControlServiceBinder(this);
}
@Override
@@ -209,6 +193,14 @@ public class VolumeControlService extends ProfileService {
}
}
+ Handler getHandler() {
+ return mHandler;
+ }
+
+ Map<BluetoothDevice, VolumeControlInputDescriptor> getAudioInputs() {
+ return mAudioInputs;
+ }
+
/**
* Get the VolumeControlService instance
*
@@ -534,7 +526,6 @@ public class VolumeControlService extends ProfileService {
mNativeInterface.setExtAudioOutVolumeOffset(device, instanceId, volumeOffset);
}
- @VisibleForTesting
synchronized void setDeviceVolume(BluetoothDevice device, int volume, boolean isGroupOp) {
Log.d(
TAG,
@@ -1685,501 +1676,6 @@ public class VolumeControlService extends ProfileService {
BluetoothProfile.VOLUME_CONTROL, device, fromState, toState);
}
- /** Binder object: must be a static class or memory leak may occur */
- @VisibleForTesting
- static class BluetoothVolumeControlBinder extends IBluetoothVolumeControl.Stub
- implements IProfileServiceBinder {
- @VisibleForTesting boolean mIsTesting = false;
- private VolumeControlService mService;
-
- BluetoothVolumeControlBinder(VolumeControlService svc) {
- mService = svc;
- }
-
- @Override
- public void cleanup() {
- mService = null;
- }
-
- @RequiresPermission(BLUETOOTH_CONNECT)
- private VolumeControlService getService(AttributionSource source) {
- requireNonNull(source);
-
- // Cache mService because it can change while getService is called
- VolumeControlService service = mService;
-
- if (Utils.isInstrumentationTestMode()) {
- return service;
- }
-
- if (!Utils.checkServiceAvailable(service, TAG)
- || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
- || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
- return null;
- }
-
- return service;
- }
-
- @Override
- public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
- VolumeControlService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getConnectedDevices();
- }
-
- @Override
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(
- int[] states, AttributionSource source) {
- VolumeControlService service = getService(source);
- if (service == null) {
- return Collections.emptyList();
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- return service.getDevicesMatchingConnectionStates(states);
- }
-
- @Override
- public int getConnectionState(BluetoothDevice device, AttributionSource source) {
- requireNonNull(device);
-
- VolumeControlService service = getService(source);
- if (service == null) {
- return STATE_DISCONNECTED;
- }
-
- return service.getConnectionState(device);
- }
-
- @Override
- public boolean setConnectionPolicy(
- BluetoothDevice device, int connectionPolicy, AttributionSource source) {
- requireNonNull(device);
-
- VolumeControlService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.setConnectionPolicy(device, connectionPolicy);
- }
-
- @Override
- public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
- requireNonNull(device);
-
- VolumeControlService service = getService(source);
- if (service == null) {
- return CONNECTION_POLICY_UNKNOWN;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getConnectionPolicy(device);
- }
-
- @Override
- public boolean isVolumeOffsetAvailable(BluetoothDevice device, AttributionSource source) {
- requireNonNull(device);
-
- VolumeControlService service = getService(source);
- if (service == null) {
- return false;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.isVolumeOffsetAvailable(device);
- }
-
- @Override
- public int getNumberOfVolumeOffsetInstances(
- BluetoothDevice device, AttributionSource source) {
- requireNonNull(device);
-
- VolumeControlService service = getService(source);
- if (service == null) {
- return 0;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- return service.getNumberOfVolumeOffsetInstances(device);
- }
-
- @Override
- public void setVolumeOffset(
- BluetoothDevice device,
- int instanceId,
- int volumeOffset,
- AttributionSource source) {
- requireNonNull(device);
-
- VolumeControlService service = getService(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.setVolumeOffset(device, instanceId, volumeOffset);
- }
-
- @Override
- public void setDeviceVolume(
- BluetoothDevice device, int volume, boolean isGroupOp, AttributionSource source) {
- requireNonNull(device);
-
- VolumeControlService service = getService(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- service.setDeviceVolume(device, volume, isGroupOp);
- }
-
- @Override
- public void setGroupVolume(int groupId, int volume, AttributionSource source) {
- VolumeControlService service = getService(source);
- if (service == null) {
- return;
- }
-
- service.setGroupVolume(groupId, volume);
- }
-
- @Override
- public int getGroupVolume(int groupId, AttributionSource source) {
- VolumeControlService service = getService(source);
- if (service == null) {
- return 0;
- }
-
- return service.getGroupVolume(groupId);
- }
-
- @Override
- public void setGroupActive(int groupId, boolean active, AttributionSource source) {
- VolumeControlService service = getService(source);
- if (service == null) {
- return;
- }
-
- service.setGroupActive(groupId, active);
- }
-
- @Override
- public void mute(BluetoothDevice device, AttributionSource source) {
- requireNonNull(device);
-
- VolumeControlService service = getService(source);
- if (service == null) {
- return;
- }
-
- service.mute(device);
- }
-
- @Override
- public void muteGroup(int groupId, AttributionSource source) {
- VolumeControlService service = getService(source);
- if (service == null) {
- return;
- }
-
- service.muteGroup(groupId);
- }
-
- @Override
- public void unmute(BluetoothDevice device, AttributionSource source) {
- requireNonNull(device);
-
- VolumeControlService service = getService(source);
- if (service == null) {
- return;
- }
-
- service.unmute(device);
- }
-
- @Override
- public void unmuteGroup(int groupId, AttributionSource source) {
- VolumeControlService service = getService(source);
- if (service == null) {
- return;
- }
-
- service.unmuteGroup(groupId);
- }
-
- private static void postAndWait(Handler handler, Runnable runnable) {
- FutureTask<Void> task = new FutureTask(Executors.callable(runnable));
-
- handler.post(task);
- try {
- task.get(1, TimeUnit.SECONDS);
- } catch (TimeoutException | InterruptedException e) {
- SneakyThrow.sneakyThrow(e);
- } catch (ExecutionException e) {
- SneakyThrow.sneakyThrow(e.getCause());
- }
- }
-
- @Override
- public void registerCallback(
- IBluetoothVolumeControlCallback callback, AttributionSource source) {
- requireNonNull(callback);
-
- VolumeControlService service = getService(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- postAndWait(service.mHandler, () -> service.registerCallback(callback));
- }
-
- @Override
- public void unregisterCallback(
- IBluetoothVolumeControlCallback callback, AttributionSource source) {
- requireNonNull(callback);
-
- VolumeControlService service = getService(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- postAndWait(service.mHandler, () -> service.unregisterCallback(callback));
- }
-
- @Override
- public void notifyNewRegisteredCallback(
- IBluetoothVolumeControlCallback callback, AttributionSource source) {
- requireNonNull(callback);
-
- VolumeControlService service = getService(source);
- if (service == null) {
- return;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
- postAndWait(service.mHandler, () -> service.notifyNewRegisteredCallback(callback));
- }
-
- private static void validateBluetoothDevice(BluetoothDevice device) {
- requireNonNull(device);
- String address = device.getAddress();
- if (!BluetoothAdapter.checkBluetoothAddress(address)) {
- throw new IllegalArgumentException("Invalid device address: " + address);
- }
- }
-
- @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED})
- private <R> R aicsWrapper(
- AttributionSource source,
- BluetoothDevice device,
- Function<VolumeControlInputDescriptor, R> fn,
- R defaultValue) {
- validateBluetoothDevice(device);
-
- VolumeControlService service = getService(source);
- if (service == null) {
- return defaultValue;
- }
-
- service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
-
- VolumeControlInputDescriptor inputs = service.mAudioInputs.get(device);
- if (inputs == null) {
- Log.w(TAG, "No audio inputs for " + device);
- return defaultValue;
- }
-
- return fn.apply(inputs);
- }
-
- @Override
- public int getNumberOfAudioInputControlServices(
- AttributionSource source, BluetoothDevice device) {
- validateBluetoothDevice(device);
- Log.d(TAG, "getNumberOfAudioInputControlServices(" + device + ")");
- return aicsWrapper(source, device, i -> i.size(), 0);
- }
-
- @Override
- public void registerAudioInputControlCallback(
- AttributionSource source,
- BluetoothDevice device,
- int instanceId,
- IAudioInputCallback callback) {
- requireNonNull(callback);
- Log.d(
- TAG,
- "registerAudioInputControlCallback("
- + (device + ", " + instanceId + ", " + callback)
- + ")");
- aicsWrapper(
- source,
- device,
- i -> {
- i.registerCallback(instanceId, callback);
- return null;
- },
- null);
- }
-
- @Override
- public void unregisterAudioInputControlCallback(
- AttributionSource source,
- BluetoothDevice device,
- int instanceId,
- IAudioInputCallback callback) {
- requireNonNull(callback);
- Log.d(
- TAG,
- "unregisterAudioInputControlCallback("
- + (device + ", " + instanceId + ", " + callback)
- + ")");
- aicsWrapper(
- source,
- device,
- i -> {
- i.unregisterCallback(instanceId, callback);
- return null;
- },
- null);
- }
-
- @Override
- public int getAudioInputGainSettingUnit(
- AttributionSource source, BluetoothDevice device, int instanceId) {
- Log.d(TAG, "getAudioInputGainSettingUnit(" + device + ", " + instanceId + ")");
- return aicsWrapper(source, device, i -> i.getGainSettingUnit(instanceId), 0);
- }
-
- @Override
- public int getAudioInputGainSettingMin(
- AttributionSource source, BluetoothDevice device, int instanceId) {
- Log.d(TAG, "getAudioInputGainSettingMin(" + device + ", " + instanceId + ")");
- return aicsWrapper(source, device, i -> i.getGainSettingMin(instanceId), 0);
- }
-
- @Override
- public int getAudioInputGainSettingMax(
- AttributionSource source, BluetoothDevice device, int instanceId) {
- Log.d(TAG, "getAudioInputGainSettingMax(" + device + ", " + instanceId + ")");
- return aicsWrapper(source, device, i -> i.getGainSettingMax(instanceId), 0);
- }
-
- @Override
- public String getAudioInputDescription(
- AttributionSource source, BluetoothDevice device, int instanceId) {
- Log.d(TAG, "getAudioInputDescription(" + device + ", " + instanceId + ")");
- return aicsWrapper(source, device, i -> i.getDescription(instanceId), "");
- }
-
- @Override
- public boolean isAudioInputDescriptionWritable(
- AttributionSource source, BluetoothDevice device, int instanceId) {
- Log.d(TAG, "isAudioInputDescriptionWritable(" + device + ", " + instanceId + ")");
- return aicsWrapper(source, device, i -> i.isDescriptionWritable(instanceId), false);
- }
-
- @Override
- public boolean setAudioInputDescription(
- AttributionSource source,
- BluetoothDevice device,
- int instanceId,
- String description) {
- requireNonNull(description);
- Log.d(TAG, "setAudioInputDescription(" + device + ", " + instanceId + ")");
- return aicsWrapper(
- source, device, i -> i.setDescription(instanceId, description), false);
- }
-
- @Override
- public @AudioInputStatus int getAudioInputStatus(
- AttributionSource source, BluetoothDevice device, int instanceId) {
- Log.d(TAG, "getAudioInputStatus(" + device + ", " + instanceId + ")");
- return aicsWrapper(
- source,
- device,
- i -> i.getStatus(instanceId),
- (int) bluetooth.constants.aics.AudioInputStatus.INACTIVE);
- }
-
- @Override
- public @AudioInputType int getAudioInputType(
- AttributionSource source, BluetoothDevice device, int instanceId) {
- Log.d(TAG, "getAudioInputType(" + device + ", " + instanceId + ")");
- return aicsWrapper(
- source,
- device,
- i -> i.getType(instanceId),
- bluetooth.constants.AudioInputType.UNSPECIFIED);
- }
-
- @Override
- public int getAudioInputGainSetting(
- AttributionSource source, BluetoothDevice device, int instanceId) {
- Log.d(TAG, "getAudioInputGainSetting(" + device + ", " + instanceId + ")");
- return aicsWrapper(source, device, i -> i.getGainSetting(instanceId), 0);
- }
-
- @Override
- public boolean setAudioInputGainSetting(
- AttributionSource source, BluetoothDevice device, int instanceId, int gainSetting) {
- Log.d(TAG, "setAudioInputGainSetting(" + device + ", " + instanceId + ")");
- return aicsWrapper(
- source, device, i -> i.setGainSetting(instanceId, gainSetting), false);
- }
-
- @Override
- public @GainMode int getAudioInputGainMode(
- AttributionSource source, BluetoothDevice device, int instanceId) {
- Log.d(TAG, "getAudioInputGainMode(" + device + ", " + instanceId + ")");
- return aicsWrapper(
- source,
- device,
- i -> i.getGainMode(instanceId),
- (int) bluetooth.constants.aics.GainMode.AUTOMATIC_ONLY);
- }
-
- @Override
- public boolean setAudioInputGainMode(
- AttributionSource source,
- BluetoothDevice device,
- int instanceId,
- @GainMode int gainMode) {
- Log.d(TAG, "setAudioInputGainMode(" + device + ", " + instanceId + ")");
- return aicsWrapper(source, device, i -> i.setGainMode(instanceId, gainMode), false);
- }
-
- @Override
- public @Mute int getAudioInputMute(
- AttributionSource source, BluetoothDevice device, int instanceId) {
- Log.d(TAG, "getAudioInputMute(" + device + ", " + instanceId + ")");
- return aicsWrapper(
- source,
- device,
- i -> i.getMute(instanceId),
- (int) bluetooth.constants.aics.Mute.DISABLED);
- }
-
- @Override
- public boolean setAudioInputMute(
- AttributionSource source, BluetoothDevice device, int instanceId, @Mute int mute) {
- Log.d(TAG, "setAudioInputMute(" + device + ", " + instanceId + ")");
- return aicsWrapper(source, device, i -> i.setMute(instanceId, mute), false);
- }
- }
-
@Override
public void dump(StringBuilder sb) {
super.dump(sb);
diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlServiceBinder.java b/android/app/src/com/android/bluetooth/vc/VolumeControlServiceBinder.java
new file mode 100644
index 0000000000..7438ab14cd
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/vc/VolumeControlServiceBinder.java
@@ -0,0 +1,528 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.vc;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.RequiresPermission;
+import android.bluetooth.AudioInputControl.AudioInputStatus;
+import android.bluetooth.AudioInputControl.AudioInputType;
+import android.bluetooth.AudioInputControl.GainMode;
+import android.bluetooth.AudioInputControl.Mute;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.IAudioInputCallback;
+import android.bluetooth.IBluetoothVolumeControl;
+import android.bluetooth.IBluetoothVolumeControlCallback;
+import android.content.AttributionSource;
+import android.os.Handler;
+import android.util.Log;
+
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
+import com.android.internal.annotations.VisibleForTesting;
+
+import libcore.util.SneakyThrow;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.function.Function;
+
+class VolumeControlServiceBinder extends IBluetoothVolumeControl.Stub
+ implements IProfileServiceBinder {
+ private static final String TAG = VolumeControlServiceBinder.class.getSimpleName();
+
+ @VisibleForTesting boolean mIsTesting = false;
+ private VolumeControlService mService;
+
+ VolumeControlServiceBinder(VolumeControlService svc) {
+ mService = svc;
+ }
+
+ @Override
+ public void cleanup() {
+ mService = null;
+ }
+
+ @RequiresPermission(BLUETOOTH_CONNECT)
+ private VolumeControlService getService(AttributionSource source) {
+ requireNonNull(source);
+
+ VolumeControlService service = mService;
+
+ if (Utils.isInstrumentationTestMode()) {
+ return service;
+ }
+
+ if (!Utils.checkServiceAvailable(service, TAG)
+ || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG)
+ || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) {
+ return null;
+ }
+
+ return service;
+ }
+
+ @Override
+ public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getConnectedDevices();
+ }
+
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ int[] states, AttributionSource source) {
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return Collections.emptyList();
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getDevicesMatchingConnectionStates(states);
+ }
+
+ @Override
+ public int getConnectionState(BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return STATE_DISCONNECTED;
+ }
+ return service.getConnectionState(device);
+ }
+
+ @Override
+ public boolean setConnectionPolicy(
+ BluetoothDevice device, int connectionPolicy, AttributionSource source) {
+ requireNonNull(device);
+
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.setConnectionPolicy(device, connectionPolicy);
+ }
+
+ @Override
+ public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return CONNECTION_POLICY_UNKNOWN;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getConnectionPolicy(device);
+ }
+
+ @Override
+ public boolean isVolumeOffsetAvailable(BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return false;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.isVolumeOffsetAvailable(device);
+ }
+
+ @Override
+ public int getNumberOfVolumeOffsetInstances(BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return 0;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ return service.getNumberOfVolumeOffsetInstances(device);
+ }
+
+ @Override
+ public void setVolumeOffset(
+ BluetoothDevice device, int instanceId, int volumeOffset, AttributionSource source) {
+ requireNonNull(device);
+
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.setVolumeOffset(device, instanceId, volumeOffset);
+ }
+
+ @Override
+ public void setDeviceVolume(
+ BluetoothDevice device, int volume, boolean isGroupOp, AttributionSource source) {
+ requireNonNull(device);
+
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ service.setDeviceVolume(device, volume, isGroupOp);
+ }
+
+ @Override
+ public void setGroupVolume(int groupId, int volume, AttributionSource source) {
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return;
+ }
+ service.setGroupVolume(groupId, volume);
+ }
+
+ @Override
+ public int getGroupVolume(int groupId, AttributionSource source) {
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return 0;
+ }
+ return service.getGroupVolume(groupId);
+ }
+
+ @Override
+ public void setGroupActive(int groupId, boolean active, AttributionSource source) {
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return;
+ }
+ service.setGroupActive(groupId, active);
+ }
+
+ @Override
+ public void mute(BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return;
+ }
+ service.mute(device);
+ }
+
+ @Override
+ public void muteGroup(int groupId, AttributionSource source) {
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return;
+ }
+ service.muteGroup(groupId);
+ }
+
+ @Override
+ public void unmute(BluetoothDevice device, AttributionSource source) {
+ requireNonNull(device);
+
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return;
+ }
+ service.unmute(device);
+ }
+
+ @Override
+ public void unmuteGroup(int groupId, AttributionSource source) {
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return;
+ }
+ service.unmuteGroup(groupId);
+ }
+
+ private static void postAndWait(Handler handler, Runnable runnable) {
+ FutureTask<Void> task = new FutureTask(Executors.callable(runnable));
+
+ handler.post(task);
+ try {
+ task.get(1, TimeUnit.SECONDS);
+ } catch (TimeoutException | InterruptedException e) {
+ SneakyThrow.sneakyThrow(e);
+ } catch (ExecutionException e) {
+ SneakyThrow.sneakyThrow(e.getCause());
+ }
+ }
+
+ @Override
+ public void registerCallback(
+ IBluetoothVolumeControlCallback callback, AttributionSource source) {
+ requireNonNull(callback);
+
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ postAndWait(service.getHandler(), () -> service.registerCallback(callback));
+ }
+
+ @Override
+ public void unregisterCallback(
+ IBluetoothVolumeControlCallback callback, AttributionSource source) {
+ requireNonNull(callback);
+
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ postAndWait(service.getHandler(), () -> service.unregisterCallback(callback));
+ }
+
+ @Override
+ public void notifyNewRegisteredCallback(
+ IBluetoothVolumeControlCallback callback, AttributionSource source) {
+ requireNonNull(callback);
+
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+ postAndWait(service.getHandler(), () -> service.notifyNewRegisteredCallback(callback));
+ }
+
+ private static void validateBluetoothDevice(BluetoothDevice device) {
+ requireNonNull(device);
+ String address = device.getAddress();
+ if (!BluetoothAdapter.checkBluetoothAddress(address)) {
+ throw new IllegalArgumentException("Invalid device address: " + address);
+ }
+ }
+
+ @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED})
+ private <R> R aicsWrapper(
+ AttributionSource source,
+ BluetoothDevice device,
+ Function<VolumeControlInputDescriptor, R> fn,
+ R defaultValue) {
+ validateBluetoothDevice(device);
+
+ VolumeControlService service = getService(source);
+ if (service == null) {
+ return defaultValue;
+ }
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+
+ VolumeControlInputDescriptor inputs = service.getAudioInputs().get(device);
+ if (inputs == null) {
+ Log.w(TAG, "No audio inputs for " + device);
+ return defaultValue;
+ }
+
+ return fn.apply(inputs);
+ }
+
+ @Override
+ public int getNumberOfAudioInputControlServices(
+ AttributionSource source, BluetoothDevice device) {
+ validateBluetoothDevice(device);
+ Log.d(TAG, "getNumberOfAudioInputControlServices(" + device + ")");
+ return aicsWrapper(source, device, i -> i.size(), 0);
+ }
+
+ @Override
+ public void registerAudioInputControlCallback(
+ AttributionSource source,
+ BluetoothDevice device,
+ int instanceId,
+ IAudioInputCallback callback) {
+ requireNonNull(callback);
+ Log.d(
+ TAG,
+ "registerAudioInputControlCallback("
+ + (device + ", " + instanceId + ", " + callback)
+ + ")");
+ aicsWrapper(
+ source,
+ device,
+ i -> {
+ i.registerCallback(instanceId, callback);
+ return null;
+ },
+ null);
+ }
+
+ @Override
+ public void unregisterAudioInputControlCallback(
+ AttributionSource source,
+ BluetoothDevice device,
+ int instanceId,
+ IAudioInputCallback callback) {
+ requireNonNull(callback);
+ Log.d(
+ TAG,
+ "unregisterAudioInputControlCallback("
+ + (device + ", " + instanceId + ", " + callback)
+ + ")");
+ aicsWrapper(
+ source,
+ device,
+ i -> {
+ i.unregisterCallback(instanceId, callback);
+ return null;
+ },
+ null);
+ }
+
+ @Override
+ public int getAudioInputGainSettingUnit(
+ AttributionSource source, BluetoothDevice device, int instanceId) {
+ Log.d(TAG, "getAudioInputGainSettingUnit(" + device + ", " + instanceId + ")");
+ return aicsWrapper(source, device, i -> i.getGainSettingUnit(instanceId), 0);
+ }
+
+ @Override
+ public int getAudioInputGainSettingMin(
+ AttributionSource source, BluetoothDevice device, int instanceId) {
+ Log.d(TAG, "getAudioInputGainSettingMin(" + device + ", " + instanceId + ")");
+ return aicsWrapper(source, device, i -> i.getGainSettingMin(instanceId), 0);
+ }
+
+ @Override
+ public int getAudioInputGainSettingMax(
+ AttributionSource source, BluetoothDevice device, int instanceId) {
+ Log.d(TAG, "getAudioInputGainSettingMax(" + device + ", " + instanceId + ")");
+ return aicsWrapper(source, device, i -> i.getGainSettingMax(instanceId), 0);
+ }
+
+ @Override
+ public String getAudioInputDescription(
+ AttributionSource source, BluetoothDevice device, int instanceId) {
+ Log.d(TAG, "getAudioInputDescription(" + device + ", " + instanceId + ")");
+ return aicsWrapper(source, device, i -> i.getDescription(instanceId), "");
+ }
+
+ @Override
+ public boolean isAudioInputDescriptionWritable(
+ AttributionSource source, BluetoothDevice device, int instanceId) {
+ Log.d(TAG, "isAudioInputDescriptionWritable(" + device + ", " + instanceId + ")");
+ return aicsWrapper(source, device, i -> i.isDescriptionWritable(instanceId), false);
+ }
+
+ @Override
+ public boolean setAudioInputDescription(
+ AttributionSource source, BluetoothDevice device, int instanceId, String description) {
+ requireNonNull(description);
+ Log.d(TAG, "setAudioInputDescription(" + device + ", " + instanceId + ")");
+ return aicsWrapper(source, device, i -> i.setDescription(instanceId, description), false);
+ }
+
+ @Override
+ public @AudioInputStatus int getAudioInputStatus(
+ AttributionSource source, BluetoothDevice device, int instanceId) {
+ Log.d(TAG, "getAudioInputStatus(" + device + ", " + instanceId + ")");
+ return aicsWrapper(
+ source,
+ device,
+ i -> i.getStatus(instanceId),
+ (int) bluetooth.constants.aics.AudioInputStatus.INACTIVE);
+ }
+
+ @Override
+ public @AudioInputType int getAudioInputType(
+ AttributionSource source, BluetoothDevice device, int instanceId) {
+ Log.d(TAG, "getAudioInputType(" + device + ", " + instanceId + ")");
+ return aicsWrapper(
+ source,
+ device,
+ i -> i.getType(instanceId),
+ bluetooth.constants.AudioInputType.UNSPECIFIED);
+ }
+
+ @Override
+ public int getAudioInputGainSetting(
+ AttributionSource source, BluetoothDevice device, int instanceId) {
+ Log.d(TAG, "getAudioInputGainSetting(" + device + ", " + instanceId + ")");
+ return aicsWrapper(source, device, i -> i.getGainSetting(instanceId), 0);
+ }
+
+ @Override
+ public boolean setAudioInputGainSetting(
+ AttributionSource source, BluetoothDevice device, int instanceId, int gainSetting) {
+ Log.d(TAG, "setAudioInputGainSetting(" + device + ", " + instanceId + ")");
+ return aicsWrapper(source, device, i -> i.setGainSetting(instanceId, gainSetting), false);
+ }
+
+ @Override
+ public @GainMode int getAudioInputGainMode(
+ AttributionSource source, BluetoothDevice device, int instanceId) {
+ Log.d(TAG, "getAudioInputGainMode(" + device + ", " + instanceId + ")");
+ return aicsWrapper(
+ source,
+ device,
+ i -> i.getGainMode(instanceId),
+ (int) bluetooth.constants.aics.GainMode.AUTOMATIC_ONLY);
+ }
+
+ @Override
+ public boolean setAudioInputGainMode(
+ AttributionSource source,
+ BluetoothDevice device,
+ int instanceId,
+ @GainMode int gainMode) {
+ Log.d(TAG, "setAudioInputGainMode(" + device + ", " + instanceId + ")");
+ return aicsWrapper(source, device, i -> i.setGainMode(instanceId, gainMode), false);
+ }
+
+ @Override
+ public @Mute int getAudioInputMute(
+ AttributionSource source, BluetoothDevice device, int instanceId) {
+ Log.d(TAG, "getAudioInputMute(" + device + ", " + instanceId + ")");
+ return aicsWrapper(
+ source,
+ device,
+ i -> i.getMute(instanceId),
+ (int) bluetooth.constants.aics.Mute.DISABLED);
+ }
+
+ @Override
+ public boolean setAudioInputMute(
+ AttributionSource source, BluetoothDevice device, int instanceId, @Mute int mute) {
+ Log.d(TAG, "setAudioInputMute(" + device + ", " + instanceId + ")");
+ return aicsWrapper(source, device, i -> i.setMute(instanceId, mute), false);
+ }
+}
diff --git a/android/app/tests/OWNERS b/android/app/tests/OWNERS
deleted file mode 100644
index ecd59038a1..0000000000
--- a/android/app/tests/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_automotive
diff --git a/android/app/tests/instrumentation/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java b/android/app/tests/instrumentation/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java
index fd9531105b..7bb7bbfbc3 100644
--- a/android/app/tests/instrumentation/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java
+++ b/android/app/tests/instrumentation/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java
@@ -46,6 +46,7 @@ import android.net.Uri;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
+import android.provider.Settings;
import android.sysprop.BluetoothProperties;
import androidx.lifecycle.Lifecycle;
@@ -382,6 +383,30 @@ public class BluetoothOppLauncherActivityTest {
assertThat(argument.getValue().getData()).isEqualTo(Uri.EMPTY);
}
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_SEND_OPP_DEVICE_PICKER_EXTRA_INTENT)
+ public void onCreate_withActionSend_grantUriPermissionToNearbyComponent() {
+ doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any());
+ doReturn(PackageManager.PERMISSION_GRANTED)
+ .when(mMethodProxy)
+ .componentCallerCheckContentUriPermission(any(), any(), anyInt());
+ String uriString = "content://test.provider/1";
+ Settings.Secure.putString(
+ mTargetContext.getContentResolver(),
+ "nearby_sharing_component",
+ "com.example/.BComponent");
+
+ ActivityScenario<BluetoothOppLauncherActivity> unused =
+ ActivityScenario.launch(createSendIntent(uriString));
+
+ verify(mMethodProxy)
+ .grantUriPermission(
+ any(),
+ eq("com.example"),
+ eq(Uri.parse(uriString)),
+ eq(Intent.FLAG_GRANT_READ_URI_PERMISSION));
+ }
+
@Ignore("b/263724420")
@Test
public void launchDevicePicker_bluetoothNotEnabled_launchEnableActivity() throws Exception {
diff --git a/android/app/tests/unit/Android.bp b/android/app/tests/unit/Android.bp
index 01d195cc43..6bf4f72d9f 100644
--- a/android/app/tests/unit/Android.bp
+++ b/android/app/tests/unit/Android.bp
@@ -35,6 +35,7 @@ android_test {
"androidx.room_room-runtime",
"androidx.room_room-testing",
"androidx.test.espresso.intents",
+ "androidx.test.ext.junit",
"androidx.test.ext.truth",
"androidx.test.rules",
"androidx.test.uiautomator_uiautomator",
@@ -45,6 +46,7 @@ android_test {
"gson",
"guava-android-testlib",
"mmslib",
+ "mockito-kotlin2",
"mockito-target-extended",
"modules-utils-handlerexecutor",
"platform-parametric-runner-lib",
@@ -61,10 +63,13 @@ android_test {
jarjar_rules: ":bluetooth-jarjar-rules",
asset_dirs: ["src/com/android/bluetooth/btservice/storage/schemas"],
- // Include all test java files.
- srcs: ["src/**/*.java"],
+ // Include all test java and kotlin files.
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ ],
jacoco: {
- include_filter: ["android.bluetooth.*"],
+ include_filter: ["com.android.bluetooth.*"],
exclude_filter: [],
},
diff --git a/android/app/tests/unit/src/com/android/bluetooth/OWNERS b/android/app/tests/unit/src/com/android/bluetooth/OWNERS
deleted file mode 100644
index 621eaef441..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# MessageQueue-related classes
-per-file TestLooper.java = mfasheh@google.com, shayba@google.com \ No newline at end of file
diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceBinderTest.java
index 23e7a5ed1c..65d00773ba 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceBinderTest.java
@@ -36,15 +36,20 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.platform.test.flag.junit.SetFlagsRule;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.Mock;
+/** Test cases for {@link A2dpServiceBinder} */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
public class A2dpServiceBinderTest {
- private static final AttributionSource sSource = new AttributionSource.Builder(0).build();
- private static final BluetoothDevice sDevice = getTestDevice(0);
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@@ -53,7 +58,10 @@ public class A2dpServiceBinderTest {
@Mock private A2dpService mA2dpService;
@Mock private PackageManager mPackageManager;
- private A2dpService.BluetoothA2dpBinder mBinder;
+ private final AttributionSource sSource = new AttributionSource.Builder(0).build();
+ private final BluetoothDevice sDevice = getTestDevice(0);
+
+ private A2dpServiceBinder mBinder;
@Before
public void setUp() throws Exception {
@@ -62,7 +70,7 @@ public class A2dpServiceBinderTest {
appInfo.targetSdkVersion = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
doReturn(appInfo).when(mPackageManager).getApplicationInfo(any(), anyInt());
- mBinder = new A2dpService.BluetoothA2dpBinder(mA2dpService);
+ mBinder = new A2dpServiceBinder(mA2dpService);
}
@After
diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceBinderTest.java
index aad4f1019a..6f7723caa9 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceBinderTest.java
@@ -27,21 +27,29 @@ import static org.mockito.Mockito.verify;
import android.bluetooth.BluetoothDevice;
import android.content.AttributionSource;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.Mock;
+/** Test cases for {@link A2dpSinkServiceBinder} */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
public class A2dpSinkServiceBinderTest {
+
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
@Mock private A2dpSinkService mService;
- private A2dpSinkService.A2dpSinkServiceBinder mBinder;
+ private A2dpSinkServiceBinder mBinder;
@Before
public void setUp() throws Exception {
- mBinder = new A2dpSinkService.A2dpSinkServiceBinder(mService);
+ mBinder = new A2dpSinkServiceBinder(mService);
}
@After
diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceBinderTest.java
index 2cbd8f356a..c4bc5dad1a 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceBinderTest.java
@@ -24,6 +24,7 @@ import static com.android.bluetooth.TestUtils.getTestDevice;
import static org.mockito.Mockito.verify;
import android.bluetooth.BluetoothDevice;
+import android.content.AttributionSource;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -34,52 +35,53 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+/** Test cases for {@link AvrcpControllerServiceBinder} */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class AvrcpControllerServiceBinderTest {
+
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
@Mock private AvrcpControllerService mService;
+ private final AttributionSource mAttributionSource = new AttributionSource.Builder(1).build();
private final BluetoothDevice mDevice = getTestDevice(49);
- AvrcpControllerService.AvrcpControllerServiceBinder mBinder;
+ private AvrcpControllerServiceBinder mBinder;
@Before
public void setUp() throws Exception {
- mBinder = new AvrcpControllerService.AvrcpControllerServiceBinder(mService);
+ mBinder = new AvrcpControllerServiceBinder(mService);
}
@Test
public void getConnectedDevices_callsServiceMethod() {
- mBinder.getConnectedDevices(null);
-
+ mBinder.getConnectedDevices(mAttributionSource);
verify(mService).getConnectedDevices();
}
@Test
public void getDevicesMatchingConnectionStates_callsServiceMethod() {
int[] states = new int[] {STATE_CONNECTED};
- mBinder.getDevicesMatchingConnectionStates(states, null);
+ mBinder.getDevicesMatchingConnectionStates(states, mAttributionSource);
verify(mService).getDevicesMatchingConnectionStates(states);
}
@Test
public void getConnectionState_callsServiceMethod() {
- mBinder.getConnectionState(mDevice, null);
-
+ mBinder.getConnectionState(mDevice, mAttributionSource);
verify(mService).getConnectionState(mDevice);
}
@Test
public void sendGroupNavigationCmd_notImplemented_doesNothing() {
- mBinder.sendGroupNavigationCmd(mDevice, 1, 2, null);
+ mBinder.sendGroupNavigationCmd(mDevice, 1, 2, mAttributionSource);
}
@Test
public void getPlayerSettings_notImplemented_doesNothing() {
- mBinder.getPlayerSettings(mDevice, null);
+ mBinder.getPlayerSettings(mDevice, mAttributionSource);
}
@Test
diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BleBroadcastAssistantBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceBinderTest.java
index ae402d7d0f..584f0cdeea 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BleBroadcastAssistantBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceBinderTest.java
@@ -36,21 +36,24 @@ import android.bluetooth.IBluetoothLeBroadcastAssistantCallback;
import android.bluetooth.le.ScanFilter;
import android.content.AttributionSource;
+import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
import org.mockito.Mock;
import org.mockito.Mockito;
import java.util.Collections;
import java.util.List;
-@RunWith(JUnit4.class)
-public class BleBroadcastAssistantBinderTest {
+/** Test cases for {@link BassClientServiceBinder} */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class BassClientServiceBinderTest {
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
@@ -64,17 +67,16 @@ public class BleBroadcastAssistantBinderTest {
@Mock private BassClientService mService;
- private BassClientService.BluetoothLeBroadcastAssistantBinder mBinder;
+ private BassClientServiceBinder mBinder;
@Before
public void setUp() {
- mBinder = new BassClientService.BluetoothLeBroadcastAssistantBinder(mService);
+ mBinder = new BassClientServiceBinder(mService);
}
@Test
public void cleanUp() {
mBinder.cleanup();
- assertThat(mBinder.mService).isNull();
}
@Test
diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/OWNERS b/android/app/tests/unit/src/com/android/bluetooth/bass_client/OWNERS
deleted file mode 100644
index a7d77894ba..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_leaudio
diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceBinderTest.java
index e7fa638eea..7e143a2851 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceBinderTest.java
@@ -23,42 +23,50 @@ import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.IBluetoothOobDataCallback;
import android.content.AttributionSource;
import android.os.ParcelUuid;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import java.io.FileDescriptor;
+/** Test cases for {@link AdapterServiceBinder} */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
public class AdapterServiceBinderTest {
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
@Mock private AdapterService mService;
@Mock private AdapterProperties mAdapterProperties;
- private AdapterService.AdapterServiceBinder mBinder;
+ private AdapterServiceBinder mBinder;
private AttributionSource mAttributionSource;
@Before
public void setUp() {
- mService.mAdapterProperties = mAdapterProperties;
+ when(mService.getAdapterProperties()).thenReturn(mAdapterProperties);
doReturn(true).when(mService).isAvailable();
doNothing().when(mService).enforceCallingOrSelfPermission(any(), any());
- mBinder = new AdapterService.AdapterServiceBinder(mService);
+ mBinder = new AdapterServiceBinder(mService);
mAttributionSource = new AttributionSource.Builder(0).build();
}
@Test
public void getAddress() {
mBinder.getAddress(mAttributionSource);
- verify(mService.mAdapterProperties).getAddress();
+ verify(mAdapterProperties).getAddress();
}
@Test
@@ -116,7 +124,7 @@ public class AdapterServiceBinderTest {
@Test
public void isActivityAndEnergyReportingSupported() {
mBinder.isActivityAndEnergyReportingSupported();
- verify(mService.mAdapterProperties).isActivityAndEnergyReportingSupported();
+ verify(mAdapterProperties).isActivityAndEnergyReportingSupported();
}
@Test
diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java
index 35190708de..6c7b1ed44e 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java
@@ -113,6 +113,7 @@ import java.util.Map;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
+/** Test cases for {@link AdapterService}. */
@MediumTest
@RunWith(ParameterizedAndroidJunit4.class)
public class AdapterServiceTest {
@@ -906,10 +907,6 @@ public class AdapterServiceTest {
// Create device properties
RemoteDevices remoteDevices = mAdapterService.getRemoteDevices();
remoteDevices.addDeviceProperties(Utils.getBytesFromAddress((TEST_BT_ADDR_1)));
- String identityAddress = mAdapterService.getIdentityAddress(TEST_BT_ADDR_1);
- if (!Flags.identityAddressNullIfNotKnown()) {
- assertThat(identityAddress).isEqualTo(TEST_BT_ADDR_1);
- }
// Trigger address consolidate callback
remoteDevices.addressConsolidateCallback(
@@ -917,7 +914,7 @@ public class AdapterServiceTest {
Utils.getBytesFromAddress(TEST_BT_ADDR_2));
// Verify we can get correct identity address
- identityAddress = mAdapterService.getIdentityAddress(TEST_BT_ADDR_1);
+ String identityAddress = mAdapterService.getIdentityAddress(TEST_BT_ADDR_1);
assertThat(identityAddress).isEqualTo(TEST_BT_ADDR_2);
assertThat(mLooper.nextMessage()).isNull();
}
@@ -954,7 +951,6 @@ public class AdapterServiceTest {
}
@Test
- @EnableFlags(Flags.FLAG_IDENTITY_ADDRESS_NULL_IF_NOT_KNOWN)
public void testIdentityAddressNullIfUnknown() {
BluetoothDevice device = getTestDevice(0);
diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java
index 1b057b3a7e..ae3db21382 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java
@@ -20,12 +20,24 @@ import static com.android.bluetooth.TestUtils.getTestDevice;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
import android.bluetooth.BluetoothDevice;
+import android.content.ContentResolver;
+import android.provider.Settings;
+import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.bluetooth.BluetoothMetricsProto.BluetoothRemoteDeviceInformation;
+import com.android.bluetooth.BluetoothStatsLog;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
@@ -37,9 +49,12 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.Mockito;
import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
import java.util.HashMap;
import java.util.Map;
@@ -236,6 +251,51 @@ public class MetricsLoggerTest {
assertThat(mTestableMetricsLogger.logAllowlistedDeviceNameHash(1, "")).isEmpty();
}
+ @Test
+ public void testUpdateHearingDeviceActiveTime() {
+ BluetoothDevice bluetoothDevice = getTestDevice(0);
+ int day = BluetoothStatsLog.HEARING_DEVICE_ACTIVE_EVENT_REPORTED__TIME_PERIOD__DAY;
+ int week = BluetoothStatsLog.HEARING_DEVICE_ACTIVE_EVENT_REPORTED__TIME_PERIOD__WEEK;
+ int month = BluetoothStatsLog.HEARING_DEVICE_ACTIVE_EVENT_REPORTED__TIME_PERIOD__MONTH;
+ doReturn(ApplicationProvider.getApplicationContext().getContentResolver())
+ .when(mAdapterService)
+ .getContentResolver();
+
+ // last active time is 2 days ago, should update last active day
+ TestableMetricsLogger logger = spy(mTestableMetricsLogger);
+ prepareLastActiveTimeDaysAgo(2);
+ logger.updateHearingDeviceActiveTime(bluetoothDevice, 1);
+ verify(logger).logHearingDeviceActiveEvent(any(), anyInt(), eq(day));
+ verify(logger, never()).logHearingDeviceActiveEvent(any(), anyInt(), eq(week));
+ verify(logger, never()).logHearingDeviceActiveEvent(any(), anyInt(), eq(month));
+
+ // last active time is 8 days ago, should update last active day and week
+ Mockito.reset(logger);
+ prepareLastActiveTimeDaysAgo(8);
+ logger.updateHearingDeviceActiveTime(bluetoothDevice, 1);
+ verify(logger).logHearingDeviceActiveEvent(any(), anyInt(), eq(day));
+ verify(logger).logHearingDeviceActiveEvent(any(), anyInt(), eq(week));
+ verify(logger, never()).logHearingDeviceActiveEvent(any(), anyInt(), eq(month));
+
+ // last active time is 60 days ago, should update last active day, week and month
+ Mockito.reset(logger);
+ prepareLastActiveTimeDaysAgo(60);
+ logger.updateHearingDeviceActiveTime(bluetoothDevice, 1);
+ verify(logger).logHearingDeviceActiveEvent(any(), anyInt(), eq(day));
+ verify(logger).logHearingDeviceActiveEvent(any(), anyInt(), eq(week));
+ verify(logger).logHearingDeviceActiveEvent(any(), anyInt(), eq(month));
+ }
+
+ private static void prepareLastActiveTimeDaysAgo(int days) {
+ final ContentResolver contentResolver =
+ ApplicationProvider.getApplicationContext().getContentResolver();
+ final LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault());
+ final String lastActive = now.minusDays(days).toString();
+ Settings.Secure.putString(contentResolver, "last_active_day", lastActive);
+ Settings.Secure.putString(contentResolver, "last_active_week", lastActive);
+ Settings.Secure.putString(contentResolver, "last_active_month", lastActive);
+ }
+
private void initTestingBloomfilter() throws IOException {
byte[] bloomfilterData =
DeviceBloomfilterGenerator.hexStringToByteArray(
diff --git a/android/app/tests/unit/src/com/android/bluetooth/content_profiles/OWNERS b/android/app/tests/unit/src/com/android/bluetooth/content_profiles/OWNERS
deleted file mode 100644
index 8f87191393..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/content_profiles/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_content \ No newline at end of file
diff --git a/android/app/tests/unit/src/com/android/bluetooth/csip/BluetoothCsisBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorServiceBinderTest.java
index 9233602c47..81adae18f4 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/csip/BluetoothCsisBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorServiceBinderTest.java
@@ -30,12 +30,20 @@ import android.bluetooth.IBluetoothCsipSetCoordinatorLockCallback;
import android.content.AttributionSource;
import android.os.ParcelUuid;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.Mock;
-public class BluetoothCsisBinderTest {
+/** Test cases for {@link CsipSetCoordinatorServiceBinder} */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class CsipSetCoordinatorServiceBinderTest {
+
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
@Mock private CsipSetCoordinatorService mService;
@@ -43,11 +51,11 @@ public class BluetoothCsisBinderTest {
private final BluetoothDevice mDevice = getTestDevice(45);
private final AttributionSource mAttributionSource = new AttributionSource.Builder(1).build();
- private CsipSetCoordinatorService.BluetoothCsisBinder mBinder;
+ private CsipSetCoordinatorServiceBinder mBinder;
@Before
public void setUp() throws Exception {
- mBinder = new CsipSetCoordinatorService.BluetoothCsisBinder(mService);
+ mBinder = new CsipSetCoordinatorServiceBinder(mService);
}
@Test
@@ -59,6 +67,7 @@ public class BluetoothCsisBinderTest {
@Test
public void getDevicesMatchingConnectionStates() {
int[] states = new int[] {STATE_CONNECTED};
+
mBinder.getDevicesMatchingConnectionStates(states, mAttributionSource);
verify(mService).getDevicesMatchingConnectionStates(states);
}
@@ -72,6 +81,7 @@ public class BluetoothCsisBinderTest {
@Test
public void setConnectionPolicy() {
int connectionPolicy = CONNECTION_POLICY_ALLOWED;
+
mBinder.setConnectionPolicy(mDevice, connectionPolicy, mAttributionSource);
verify(mService).setConnectionPolicy(mDevice, connectionPolicy);
}
@@ -87,6 +97,7 @@ public class BluetoothCsisBinderTest {
int groupId = 100;
IBluetoothCsipSetCoordinatorLockCallback cb =
mock(IBluetoothCsipSetCoordinatorLockCallback.class);
+
mBinder.lockGroup(groupId, cb, mAttributionSource);
verify(mService).lockGroup(groupId, cb);
}
@@ -94,6 +105,7 @@ public class BluetoothCsisBinderTest {
@Test
public void unlockGroup() {
ParcelUuid uuid = ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB");
+
mBinder.unlockGroup(uuid, mAttributionSource);
verify(mService).unlockGroup(uuid.getUuid());
}
@@ -101,6 +113,7 @@ public class BluetoothCsisBinderTest {
@Test
public void getAllGroupIds() {
ParcelUuid uuid = ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB");
+
mBinder.getAllGroupIds(uuid, mAttributionSource);
verify(mService).getAllGroupIds(uuid);
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorServiceTest.java
index ac64b097ae..72fbd125b6 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorServiceTest.java
@@ -130,7 +130,6 @@ public class CsipSetCoordinatorServiceTest {
new CsipSetCoordinatorService(
mAdapterService, mLooper.getLooper(), mNativeInterface, mServiceFactory);
mService.setAvailable(true);
-
}
@After
diff --git a/android/app/tests/unit/src/com/android/bluetooth/csip/OWNERS b/android/app/tests/unit/src/com/android/bluetooth/csip/OWNERS
deleted file mode 100644
index a7d77894ba..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/csip/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_leaudio
diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseBinderTest.java
deleted file mode 100644
index c78c9ec6db..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseBinderTest.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2025 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.bluetooth.gatt;
-
-import static com.android.bluetooth.TestUtils.MockitoRule;
-
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import android.bluetooth.BluetoothManager;
-import android.bluetooth.le.AdvertiseData;
-import android.bluetooth.le.AdvertisingSetParameters;
-import android.bluetooth.le.IAdvertisingSetCallback;
-import android.bluetooth.le.PeriodicAdvertisingParameters;
-import android.content.AttributionSource;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.bluetooth.btservice.AdapterService;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-
-/** Test cases for {@link AdvertiseBinder}. */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class AdvertiseBinderTest {
- @Rule public final MockitoRule mMockitoRule = new MockitoRule();
-
- @Mock private AdapterService mAdapterService;
- @Mock private AdvertiseManager mAdvertiseManager;
-
- private final AttributionSource mAttributionSource =
- InstrumentationRegistry.getInstrumentation()
- .getTargetContext()
- .getSystemService(BluetoothManager.class)
- .getAdapter()
- .getAttributionSource();
- private AdvertiseBinder mBinder;
-
- @Before
- public void setUp() {
- doAnswer(
- invocation -> {
- ((Runnable) invocation.getArgument(0)).run();
- return null;
- })
- .when(mAdvertiseManager)
- .doOnAdvertiseThread(any());
- mBinder = new AdvertiseBinder(mAdapterService, mAdvertiseManager);
- }
-
- @Test
- public void startAdvertisingSet() {
- AdvertisingSetParameters parameters = new AdvertisingSetParameters.Builder().build();
- AdvertiseData advertiseData = new AdvertiseData.Builder().build();
- AdvertiseData scanResponse = new AdvertiseData.Builder().build();
- PeriodicAdvertisingParameters periodicParameters =
- new PeriodicAdvertisingParameters.Builder().build();
- AdvertiseData periodicData = new AdvertiseData.Builder().build();
- int duration = 1;
- int maxExtAdvEvents = 2;
- int serverIf = 3;
- IAdvertisingSetCallback callback = mock(IAdvertisingSetCallback.class);
-
- mBinder.startAdvertisingSet(
- parameters,
- advertiseData,
- scanResponse,
- periodicParameters,
- periodicData,
- duration,
- maxExtAdvEvents,
- serverIf,
- callback,
- mAttributionSource);
-
- verify(mAdvertiseManager)
- .startAdvertisingSet(
- parameters,
- advertiseData,
- scanResponse,
- periodicParameters,
- periodicData,
- duration,
- maxExtAdvEvents,
- serverIf,
- callback,
- mAttributionSource);
- }
-
- @Test
- public void stopAdvertisingSet() {
- IAdvertisingSetCallback callback = mock(IAdvertisingSetCallback.class);
-
- mBinder.stopAdvertisingSet(callback, mAttributionSource);
-
- verify(mAdvertiseManager).stopAdvertisingSet(callback);
- }
-
- @Test
- public void setAdvertisingData() {
- int advertiserId = 1;
- AdvertiseData data = new AdvertiseData.Builder().build();
-
- mBinder.setAdvertisingData(advertiserId, data, mAttributionSource);
- verify(mAdvertiseManager).setAdvertisingData(advertiserId, data);
- }
-
- @Test
- public void setAdvertisingParameters() {
- int advertiserId = 1;
- AdvertisingSetParameters parameters = new AdvertisingSetParameters.Builder().build();
-
- mBinder.setAdvertisingParameters(advertiserId, parameters, mAttributionSource);
- verify(mAdvertiseManager).setAdvertisingParameters(advertiserId, parameters);
- }
-
- @Test
- public void setPeriodicAdvertisingData() {
- int advertiserId = 1;
- AdvertiseData data = new AdvertiseData.Builder().build();
-
- mBinder.setPeriodicAdvertisingData(advertiserId, data, mAttributionSource);
- verify(mAdvertiseManager).setPeriodicAdvertisingData(advertiserId, data);
- }
-
- @Test
- public void setPeriodicAdvertisingEnable() {
- int advertiserId = 1;
- boolean enable = true;
-
- mBinder.setPeriodicAdvertisingEnable(advertiserId, enable, mAttributionSource);
- verify(mAdvertiseManager).setPeriodicAdvertisingEnable(advertiserId, enable);
- }
-
- @Test
- public void setPeriodicAdvertisingParameters() {
- int advertiserId = 1;
- PeriodicAdvertisingParameters parameters =
- new PeriodicAdvertisingParameters.Builder().build();
-
- mBinder.setPeriodicAdvertisingParameters(advertiserId, parameters, mAttributionSource);
- verify(mAdvertiseManager).setPeriodicAdvertisingParameters(advertiserId, parameters);
- }
-
- @Test
- public void setScanResponseData() {
- int advertiserId = 1;
- AdvertiseData data = new AdvertiseData.Builder().build();
-
- mBinder.setScanResponseData(advertiserId, data, mAttributionSource);
- verify(mAdvertiseManager).setScanResponseData(advertiserId, data);
- }
-
- @Test
- public void getOwnAddress() {
- int advertiserId = 1;
-
- mBinder.getOwnAddress(advertiserId, mAttributionSource);
- verify(mAdvertiseManager).getOwnAddress(advertiserId);
- }
-
- @Test
- public void enableAdvertisingSet() {
- int advertiserId = 1;
- boolean enable = true;
- int duration = 3;
- int maxExtAdvEvents = 4;
-
- mBinder.enableAdvertisingSet(
- advertiserId, enable, duration, maxExtAdvEvents, mAttributionSource);
- verify(mAdvertiseManager)
- .enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents);
- }
-
- @Test
- public void cleanUp_doesNotCrash() {
- mBinder.cleanup();
- }
-}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseBinderTest.kt b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseBinderTest.kt
new file mode 100644
index 0000000000..6b038678f0
--- /dev/null
+++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseBinderTest.kt
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.gatt
+
+import android.bluetooth.BluetoothManager
+import android.bluetooth.le.AdvertiseData
+import android.bluetooth.le.AdvertisingSetParameters
+import android.bluetooth.le.IAdvertisingSetCallback
+import android.bluetooth.le.PeriodicAdvertisingParameters
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.bluetooth.TestUtils.MockitoRule
+import com.android.bluetooth.btservice.AdapterService
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.any
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.verify
+import org.mockito.kotlin.whenever
+
+/** Test cases for [AdvertiseBinder] */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class AdvertiseBinderTest {
+
+ @get:Rule val mockitoRule = MockitoRule()
+
+ @Mock private lateinit var adapterService: AdapterService
+ @Mock private lateinit var advertiseManager: AdvertiseManager
+
+ private val attributionSource =
+ InstrumentationRegistry.getInstrumentation()
+ .targetContext
+ .getSystemService(BluetoothManager::class.java)
+ .adapter
+ .attributionSource
+
+ private lateinit var binder: AdvertiseBinder
+
+ @Before
+ fun setUp() {
+ doAnswer { invocation ->
+ (invocation.getArgument(0) as Runnable).run()
+ null
+ }
+ .whenever(advertiseManager)
+ .doOnAdvertiseThread(any())
+ binder = AdvertiseBinder(adapterService, advertiseManager)
+ }
+
+ @Test
+ fun startAdvertisingSet() {
+ val parameters = AdvertisingSetParameters.Builder().build()
+ val advertiseData = AdvertiseData.Builder().build()
+ val scanResponse = AdvertiseData.Builder().build()
+ val periodicParameters = PeriodicAdvertisingParameters.Builder().build()
+ val periodicData = AdvertiseData.Builder().build()
+ val duration = 1
+ val maxExtAdvEvents = 2
+ val serverIf = 3
+ val callback = mock(IAdvertisingSetCallback::class.java)
+
+ binder.startAdvertisingSet(
+ parameters,
+ advertiseData,
+ scanResponse,
+ periodicParameters,
+ periodicData,
+ duration,
+ maxExtAdvEvents,
+ serverIf,
+ callback,
+ attributionSource,
+ )
+ verify(advertiseManager)
+ .startAdvertisingSet(
+ parameters,
+ advertiseData,
+ scanResponse,
+ periodicParameters,
+ periodicData,
+ duration,
+ maxExtAdvEvents,
+ serverIf,
+ callback,
+ attributionSource,
+ )
+ }
+
+ @Test
+ fun stopAdvertisingSet() {
+ val callback = mock(IAdvertisingSetCallback::class.java)
+
+ binder.stopAdvertisingSet(callback, attributionSource)
+ verify(advertiseManager).stopAdvertisingSet(callback)
+ }
+
+ @Test
+ fun setAdvertisingData() {
+ val advertiserId = 1
+ val data = AdvertiseData.Builder().build()
+
+ binder.setAdvertisingData(advertiserId, data, attributionSource)
+ verify(advertiseManager).setAdvertisingData(advertiserId, data)
+ }
+
+ @Test
+ fun setAdvertisingParameters() {
+ val advertiserId = 1
+ val parameters = AdvertisingSetParameters.Builder().build()
+
+ binder.setAdvertisingParameters(advertiserId, parameters, attributionSource)
+ verify(advertiseManager).setAdvertisingParameters(advertiserId, parameters)
+ }
+
+ @Test
+ fun setPeriodicAdvertisingData() {
+ val advertiserId = 1
+ val data = AdvertiseData.Builder().build()
+
+ binder.setPeriodicAdvertisingData(advertiserId, data, attributionSource)
+ verify(advertiseManager).setPeriodicAdvertisingData(advertiserId, data)
+ }
+
+ @Test
+ fun setPeriodicAdvertisingEnable() {
+ val advertiserId = 1
+ val enable = true
+
+ binder.setPeriodicAdvertisingEnable(advertiserId, enable, attributionSource)
+ verify(advertiseManager).setPeriodicAdvertisingEnable(advertiserId, enable)
+ }
+
+ @Test
+ fun setPeriodicAdvertisingParameters() {
+ val advertiserId = 1
+ val parameters = PeriodicAdvertisingParameters.Builder().build()
+
+ binder.setPeriodicAdvertisingParameters(advertiserId, parameters, attributionSource)
+ verify(advertiseManager).setPeriodicAdvertisingParameters(advertiserId, parameters)
+ }
+
+ @Test
+ fun setScanResponseData() {
+ val advertiserId = 1
+ val data = AdvertiseData.Builder().build()
+
+ binder.setScanResponseData(advertiserId, data, attributionSource)
+ verify(advertiseManager).setScanResponseData(advertiserId, data)
+ }
+
+ @Test
+ fun getOwnAddress() {
+ val advertiserId = 1
+
+ binder.getOwnAddress(advertiserId, attributionSource)
+ verify(advertiseManager).getOwnAddress(advertiserId)
+ }
+
+ @Test
+ fun enableAdvertisingSet() {
+ val advertiserId = 1
+ val enable = true
+ val duration = 3
+ val maxExtAdvEvents = 4
+
+ binder.enableAdvertisingSet(
+ advertiserId,
+ enable,
+ duration,
+ maxExtAdvEvents,
+ attributionSource,
+ )
+ verify(advertiseManager)
+ .enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents)
+ }
+
+ @Test
+ fun cleanup_doesNotCrash() {
+ binder.cleanup()
+ }
+}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/AppAdvertiseStatsTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/AppAdvertiseStatsTest.java
index 86a26e5ad9..e2bcfb75e2 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/gatt/AppAdvertiseStatsTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/AppAdvertiseStatsTest.java
@@ -305,7 +305,6 @@ public class AppAdvertiseStatsTest {
}
@Test
- @EnableFlags(Flags.FLAG_BLE_SCAN_ADV_METRICS_REDESIGN)
public void testAdvertiseCounterMetrics() {
int appUid = 0;
int id = 1;
@@ -356,7 +355,8 @@ public class AppAdvertiseStatsTest {
true,
instanceCount,
0,
- IMPORTANCE_FOREGROUND_SERVICE);
+ IMPORTANCE_FOREGROUND_SERVICE,
+ "");
Mockito.clearInvocations(mMetricsLogger);
// Wait for adv test duration
@@ -390,7 +390,8 @@ public class AppAdvertiseStatsTest {
eq(true),
eq(instanceCount),
mAdvDurationCaptor.capture(),
- eq(IMPORTANCE_FOREGROUND_SERVICE));
+ eq(IMPORTANCE_FOREGROUND_SERVICE),
+ eq(""));
long capturedAppScanDuration = mAdvDurationCaptor.getValue();
Log.d(TAG, "capturedDuration: " + capturedAppScanDuration);
assertThat(capturedAppScanDuration).isAtLeast(advTestDuration);
diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementBinderTest.java
deleted file mode 100644
index a65c805a47..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementBinderTest.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2025 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.bluetooth.gatt;
-
-import static com.android.bluetooth.TestUtils.MockitoRule;
-import static com.android.bluetooth.TestUtils.getTestDevice;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothManager;
-import android.bluetooth.le.DistanceMeasurementMethod;
-import android.bluetooth.le.DistanceMeasurementParams;
-import android.bluetooth.le.IDistanceMeasurementCallback;
-import android.content.AttributionSource;
-import android.os.ParcelUuid;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.bluetooth.btservice.AdapterService;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-
-import java.util.Collections;
-import java.util.UUID;
-
-/** Test cases for {@link DistanceMeasurementBinder}. */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class DistanceMeasurementBinderTest {
- @Rule public final MockitoRule mMockitoRule = new MockitoRule();
-
- @Mock private DistanceMeasurementManager mDistanceMeasurementManager;
- @Mock private AdapterService mAdapterService;
-
- private final AttributionSource mAttributionSource =
- InstrumentationRegistry.getInstrumentation()
- .getTargetContext()
- .getSystemService(BluetoothManager.class)
- .getAdapter()
- .getAttributionSource();
-
- private DistanceMeasurementBinder mBinder;
-
- @Before
- public void setUp() throws Throwable {
- mBinder = new DistanceMeasurementBinder(mAdapterService, mDistanceMeasurementManager);
- when(mDistanceMeasurementManager.getSupportedDistanceMeasurementMethods())
- .thenReturn(Collections.emptyList());
- when(mDistanceMeasurementManager.runOnDistanceMeasurementThreadAndWaitForResult(any()))
- .thenAnswer(
- invocationOnMock -> {
- DistanceMeasurementManager.GetResultTask task =
- invocationOnMock.getArgument(0);
- return task.getResult();
- });
- doAnswer(
- invocation -> {
- ((Runnable) (invocation.getArgument(0))).run();
- return null;
- })
- .when(mDistanceMeasurementManager)
- .postOnDistanceMeasurementThread(any());
- }
-
- @Test
- public void getSupportedDistanceMeasurementMethods() {
- mBinder.getSupportedDistanceMeasurementMethods(mAttributionSource);
- verify(mDistanceMeasurementManager).getSupportedDistanceMeasurementMethods();
- }
-
- @Test
- public void startDistanceMeasurement() {
- UUID uuid = UUID.randomUUID();
- BluetoothDevice device = getTestDevice(3);
- DistanceMeasurementParams params =
- new DistanceMeasurementParams.Builder(device)
- .setDurationSeconds(123)
- .setFrequency(DistanceMeasurementParams.REPORT_FREQUENCY_LOW)
- .build();
- IDistanceMeasurementCallback callback = mock(IDistanceMeasurementCallback.class);
- mBinder.startDistanceMeasurement(
- new ParcelUuid(uuid), params, callback, mAttributionSource);
- verify(mDistanceMeasurementManager).startDistanceMeasurement(uuid, params, callback);
- }
-
- @Test
- public void stopDistanceMeasurement() {
- UUID uuid = UUID.randomUUID();
- BluetoothDevice device = getTestDevice(3);
- int method = DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI;
- mBinder.stopDistanceMeasurement(new ParcelUuid(uuid), device, method, mAttributionSource);
- verify(mDistanceMeasurementManager).stopDistanceMeasurement(uuid, device, method, false);
- }
-}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementBinderTest.kt b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementBinderTest.kt
new file mode 100644
index 0000000000..b20eda9a17
--- /dev/null
+++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementBinderTest.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.gatt
+
+import android.bluetooth.BluetoothDevice
+import android.bluetooth.BluetoothManager
+import android.bluetooth.le.DistanceMeasurementMethod
+import android.bluetooth.le.DistanceMeasurementParams
+import android.bluetooth.le.IDistanceMeasurementCallback
+import android.os.ParcelUuid
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.bluetooth.TestUtils.MockitoRule
+import com.android.bluetooth.TestUtils.getTestDevice
+import com.android.bluetooth.btservice.AdapterService
+import com.android.bluetooth.gatt.DistanceMeasurementManager.GetResultTask
+import java.util.UUID
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.any
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.verify
+import org.mockito.kotlin.whenever
+
+/** Test cases for [DistanceMeasurementBinder] */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DistanceMeasurementBinderTest {
+
+ @get:Rule val mockitoRule = MockitoRule()
+
+ @Mock private lateinit var distanceMeasurementManager: DistanceMeasurementManager
+ @Mock private lateinit var adapterService: AdapterService
+
+ private val attributionSource =
+ InstrumentationRegistry.getInstrumentation()
+ .targetContext
+ .getSystemService(BluetoothManager::class.java)
+ .adapter
+ .attributionSource
+
+ private lateinit var binder: DistanceMeasurementBinder
+
+ @Before
+ fun setUp() {
+ binder = DistanceMeasurementBinder(adapterService, distanceMeasurementManager)
+ doReturn(emptyList<DistanceMeasurementMethod>())
+ .whenever(distanceMeasurementManager)
+ .getSupportedDistanceMeasurementMethods()
+ doAnswer { invocationOnMock ->
+ val task = invocationOnMock.getArgument<GetResultTask<*>>(0)
+ task.result
+ }
+ .whenever(distanceMeasurementManager)
+ .runOnDistanceMeasurementThreadAndWaitForResult(any<GetResultTask<*>>())
+ doAnswer { invocation ->
+ (invocation.getArgument(0) as Runnable).run()
+ null
+ }
+ .whenever(distanceMeasurementManager)
+ .postOnDistanceMeasurementThread(any())
+ }
+
+ @Test
+ fun getSupportedDistanceMeasurementMethods() {
+ binder.getSupportedDistanceMeasurementMethods(attributionSource)
+ verify(distanceMeasurementManager).supportedDistanceMeasurementMethods
+ }
+
+ @Test
+ fun startDistanceMeasurement() {
+ val uuid = UUID.randomUUID()
+ val device: BluetoothDevice = getTestDevice(3)
+ val params =
+ DistanceMeasurementParams.Builder(device)
+ .setDurationSeconds(123)
+ .setFrequency(DistanceMeasurementParams.REPORT_FREQUENCY_LOW)
+ .build()
+ val callback = mock(IDistanceMeasurementCallback::class.java)
+ binder.startDistanceMeasurement(ParcelUuid(uuid), params, callback, attributionSource)
+ verify(distanceMeasurementManager).startDistanceMeasurement(uuid, params, callback)
+ }
+
+ @Test
+ fun stopDistanceMeasurement() {
+ val uuid = UUID.randomUUID()
+ val device: BluetoothDevice = getTestDevice(3)
+ val method = DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI
+ binder.stopDistanceMeasurement(ParcelUuid(uuid), device, method, attributionSource)
+ verify(distanceMeasurementManager).stopDistanceMeasurement(uuid, device, method, false)
+ }
+}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceBinderTest.java
index 36e96f6007..f9bb1d556d 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceBinderTest.java
@@ -42,6 +42,7 @@ import org.mockito.Mock;
import java.util.UUID;
+/** Test cases for {@link GattServiceBinder} */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class GattServiceBinderTest {
@@ -53,13 +54,12 @@ public class GattServiceBinderTest {
@Mock private GattService mService;
private AttributionSource mAttributionSource;
-
- private GattService.BluetoothGattBinder mBinder;
+ private GattServiceBinder mBinder;
@Before
public void setUp() throws Exception {
when(mService.isAvailable()).thenReturn(true);
- mBinder = new GattService.BluetoothGattBinder(mService);
+ mBinder = new GattServiceBinder(mService);
mAttributionSource = new AttributionSource.Builder(1).build();
}
@@ -68,7 +68,6 @@ public class GattServiceBinderTest {
int[] states = new int[] {STATE_CONNECTED};
mBinder.getDevicesMatchingConnectionStates(states, mAttributionSource);
-
verify(mService).getDevicesMatchingConnectionStates(states, mAttributionSource);
}
@@ -79,7 +78,6 @@ public class GattServiceBinderTest {
boolean eattSupport = true;
mBinder.registerClient(new ParcelUuid(uuid), callback, eattSupport, mAttributionSource);
-
verify(mService).registerClient(uuid, callback, eattSupport, mAttributionSource);
}
@@ -88,7 +86,6 @@ public class GattServiceBinderTest {
int clientIf = 3;
mBinder.unregisterClient(clientIf, mAttributionSource);
-
verify(mService)
.unregisterClient(
clientIf,
@@ -115,7 +112,6 @@ public class GattServiceBinderTest {
opportunistic,
phy,
mAttributionSource);
-
verify(mService)
.clientConnect(
clientIf,
@@ -134,7 +130,6 @@ public class GattServiceBinderTest {
String address = REMOTE_DEVICE_ADDRESS;
mBinder.clientDisconnect(clientIf, address, mAttributionSource);
-
verify(mService).clientDisconnect(clientIf, address, mAttributionSource);
}
@@ -148,7 +143,6 @@ public class GattServiceBinderTest {
mBinder.clientSetPreferredPhy(
clientIf, address, txPhy, rxPhy, phyOptions, mAttributionSource);
-
verify(mService)
.clientSetPreferredPhy(
clientIf, address, txPhy, rxPhy, phyOptions, mAttributionSource);
@@ -160,7 +154,6 @@ public class GattServiceBinderTest {
String address = REMOTE_DEVICE_ADDRESS;
mBinder.clientReadPhy(clientIf, address, mAttributionSource);
-
verify(mService).clientReadPhy(clientIf, address, mAttributionSource);
}
@@ -170,7 +163,6 @@ public class GattServiceBinderTest {
String address = REMOTE_DEVICE_ADDRESS;
mBinder.refreshDevice(clientIf, address, mAttributionSource);
-
verify(mService).refreshDevice(clientIf, address, mAttributionSource);
}
@@ -180,7 +172,6 @@ public class GattServiceBinderTest {
String address = REMOTE_DEVICE_ADDRESS;
mBinder.discoverServices(clientIf, address, mAttributionSource);
-
verify(mService).discoverServices(clientIf, address, mAttributionSource);
}
@@ -191,7 +182,6 @@ public class GattServiceBinderTest {
UUID uuid = UUID.randomUUID();
mBinder.discoverServiceByUuid(clientIf, address, new ParcelUuid(uuid), mAttributionSource);
-
verify(mService).discoverServiceByUuid(clientIf, address, uuid, mAttributionSource);
}
@@ -203,7 +193,6 @@ public class GattServiceBinderTest {
int authReq = 3;
mBinder.readCharacteristic(clientIf, address, handle, authReq, mAttributionSource);
-
verify(mService).readCharacteristic(clientIf, address, handle, authReq, mAttributionSource);
}
@@ -224,7 +213,6 @@ public class GattServiceBinderTest {
endHandle,
authReq,
mAttributionSource);
-
verify(mService)
.readUsingCharacteristicUuid(
clientIf,
@@ -247,7 +235,6 @@ public class GattServiceBinderTest {
mBinder.writeCharacteristic(
clientIf, address, handle, writeType, authReq, value, mAttributionSource);
-
verify(mService)
.writeCharacteristic(
clientIf, address, handle, writeType, authReq, value, mAttributionSource);
@@ -261,7 +248,6 @@ public class GattServiceBinderTest {
int authReq = 3;
mBinder.readDescriptor(clientIf, address, handle, authReq, mAttributionSource);
-
verify(mService).readDescriptor(clientIf, address, handle, authReq, mAttributionSource);
}
@@ -274,7 +260,6 @@ public class GattServiceBinderTest {
byte[] value = new byte[] {4, 5};
mBinder.writeDescriptor(clientIf, address, handle, authReq, value, mAttributionSource);
-
verify(mService)
.writeDescriptor(clientIf, address, handle, authReq, value, mAttributionSource);
}
@@ -285,7 +270,6 @@ public class GattServiceBinderTest {
String address = REMOTE_DEVICE_ADDRESS;
mBinder.beginReliableWrite(clientIf, address, mAttributionSource);
-
verify(mService).beginReliableWrite(clientIf, address, mAttributionSource);
}
@@ -296,7 +280,6 @@ public class GattServiceBinderTest {
boolean execute = true;
mBinder.endReliableWrite(clientIf, address, execute, mAttributionSource);
-
verify(mService).endReliableWrite(clientIf, address, execute, mAttributionSource);
}
@@ -308,7 +291,6 @@ public class GattServiceBinderTest {
boolean enable = true;
mBinder.registerForNotification(clientIf, address, handle, enable, mAttributionSource);
-
verify(mService)
.registerForNotification(clientIf, address, handle, enable, mAttributionSource);
}
@@ -319,7 +301,6 @@ public class GattServiceBinderTest {
String address = REMOTE_DEVICE_ADDRESS;
mBinder.readRemoteRssi(clientIf, address, mAttributionSource);
-
verify(mService).readRemoteRssi(clientIf, address, mAttributionSource);
}
@@ -330,7 +311,6 @@ public class GattServiceBinderTest {
int mtu = 2;
mBinder.configureMTU(clientIf, address, mtu, mAttributionSource);
-
verify(mService).configureMTU(clientIf, address, mtu, mAttributionSource);
}
@@ -342,7 +322,6 @@ public class GattServiceBinderTest {
mBinder.connectionParameterUpdate(
clientIf, address, connectionPriority, mAttributionSource);
-
verify(mService)
.connectionParameterUpdate(
clientIf, address, connectionPriority, mAttributionSource);
@@ -369,7 +348,6 @@ public class GattServiceBinderTest {
minConnectionEventLen,
maxConnectionEventLen,
mAttributionSource);
-
verify(mService)
.leConnectionUpdate(
clientIf,
@@ -390,7 +368,6 @@ public class GattServiceBinderTest {
boolean eattSupport = true;
mBinder.registerServer(new ParcelUuid(uuid), callback, eattSupport, mAttributionSource);
-
verify(mService).registerServer(uuid, callback, eattSupport, mAttributionSource);
}
@@ -399,7 +376,6 @@ public class GattServiceBinderTest {
int serverIf = 3;
mBinder.unregisterServer(serverIf, mAttributionSource);
-
verify(mService).unregisterServer(serverIf, mAttributionSource);
}
@@ -413,7 +389,6 @@ public class GattServiceBinderTest {
mBinder.serverConnect(
serverIf, address, addressType, isDirect, transport, mAttributionSource);
-
verify(mService)
.serverConnect(
serverIf, address, addressType, isDirect, transport, mAttributionSource);
@@ -425,7 +400,6 @@ public class GattServiceBinderTest {
String address = REMOTE_DEVICE_ADDRESS;
mBinder.serverDisconnect(serverIf, address, mAttributionSource);
-
verify(mService).serverDisconnect(serverIf, address, mAttributionSource);
}
@@ -439,7 +413,6 @@ public class GattServiceBinderTest {
mBinder.serverSetPreferredPhy(
serverIf, address, txPhy, rxPhy, phyOptions, mAttributionSource);
-
verify(mService)
.serverSetPreferredPhy(
serverIf, address, txPhy, rxPhy, phyOptions, mAttributionSource);
@@ -451,7 +424,6 @@ public class GattServiceBinderTest {
String address = REMOTE_DEVICE_ADDRESS;
mBinder.serverReadPhy(serverIf, address, mAttributionSource);
-
verify(mService).serverReadPhy(serverIf, address, mAttributionSource);
}
@@ -461,7 +433,6 @@ public class GattServiceBinderTest {
BluetoothGattService svc = mock(BluetoothGattService.class);
mBinder.addService(serverIf, svc, mAttributionSource);
-
verify(mService).addService(serverIf, svc, mAttributionSource);
}
@@ -471,7 +442,6 @@ public class GattServiceBinderTest {
int handle = 2;
mBinder.removeService(serverIf, handle, mAttributionSource);
-
verify(mService).removeService(serverIf, handle, mAttributionSource);
}
@@ -480,7 +450,6 @@ public class GattServiceBinderTest {
int serverIf = 1;
mBinder.clearServices(serverIf, mAttributionSource);
-
verify(mService).clearServices(serverIf, mAttributionSource);
}
@@ -495,7 +464,6 @@ public class GattServiceBinderTest {
mBinder.sendResponse(
serverIf, address, requestId, status, offset, value, mAttributionSource);
-
verify(mService)
.sendResponse(
serverIf, address, requestId, status, offset, value, mAttributionSource);
@@ -510,7 +478,6 @@ public class GattServiceBinderTest {
byte[] value = new byte[] {5, 6};
mBinder.sendNotification(serverIf, address, handle, confirm, value, mAttributionSource);
-
verify(mService)
.sendNotification(serverIf, address, handle, confirm, value, mAttributionSource);
}
@@ -518,12 +485,11 @@ public class GattServiceBinderTest {
@Test
public void disconnectAll() throws Exception {
mBinder.disconnectAll(mAttributionSource);
-
verify(mService).disconnectAll(mAttributionSource);
}
@Test
- public void cleanUp_doesNotCrash() {
+ public void cleanup_doesNotCrash() {
mBinder.cleanup();
}
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java
index 76d6dd53ff..1e8a55b994 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java
@@ -42,7 +42,6 @@ import android.content.res.Resources;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Process;
-import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;
@@ -54,7 +53,6 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.bluetooth.TestUtils;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.CompanionManager;
-import com.android.bluetooth.flags.Flags;
import com.android.bluetooth.le_scan.PeriodicScanManager;
import com.android.bluetooth.le_scan.ScanManager;
import com.android.bluetooth.le_scan.ScanObjectsFactory;
@@ -79,7 +77,6 @@ import java.util.UUID;
@RunWith(AndroidJUnit4.class)
public class GattServiceTest {
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
- @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Mock private ContextMap<IBluetoothGattCallback> mClientMap;
@Mock private ScanManager mScanManager;
@@ -443,7 +440,6 @@ public class GattServiceTest {
@Test
public void registerClient_checkLimitPerApp() {
- mSetFlagsRule.enableFlags(Flags.FLAG_GATT_CLIENT_DYNAMIC_ALLOCATION);
doReturn(GattService.GATT_CLIENT_LIMIT_PER_APP).when(mClientMap).countByAppUid(anyInt());
UUID uuid = UUID.randomUUID();
IBluetoothGattCallback callback = mock(IBluetoothGattCallback.class);
diff --git a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientServiceBinderTest.java
index dd5ede57b2..3544578497 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientServiceBinderTest.java
@@ -44,9 +44,10 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
+/** Test cases for {@link HapClientServiceBinder} */
@MediumTest
@RunWith(AndroidJUnit4.class)
-public class HapClientBinderTest {
+public class HapClientServiceBinderTest {
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
@Mock private HapClientService mHapClientService;
@@ -59,11 +60,11 @@ public class HapClientBinderTest {
private final AttributionSource mAttributionSource = mAdapter.getAttributionSource();
private final BluetoothDevice mDevice = getTestDevice(0);
- private HapClientBinder mBinder;
+ private HapClientServiceBinder mBinder;
@Before
public void setUp() throws Exception {
- mBinder = new HapClientBinder(mHapClientService);
+ mBinder = new HapClientServiceBinder(mHapClientService);
}
@Test
diff --git a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceBinderTest.java
new file mode 100644
index 0000000000..8dae3bf594
--- /dev/null
+++ b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceBinderTest.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.hearingaid;
+
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+
+import static com.android.bluetooth.TestUtils.MockitoRule;
+import static com.android.bluetooth.TestUtils.getTestDevice;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothManager;
+import android.content.AttributionSource;
+import android.content.Context;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** Test cases for {@link HearingAidServiceBinder} */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class HearingAidServiceBinderTest {
+
+ @Rule public final MockitoRule mMockitoRule = new MockitoRule();
+
+ @Mock private HearingAidService mService;
+
+ private HearingAidServiceBinder mBinder;
+ private AttributionSource mAttributionSource;
+ private BluetoothDevice mTestDevice;
+
+ @Before
+ public void setUp() throws Exception {
+ when(mService.isAvailable()).thenReturn(true);
+ mBinder = new HearingAidServiceBinder(mService);
+ Context context = InstrumentationRegistry.getTargetContext();
+ mAttributionSource =
+ context.getSystemService(BluetoothManager.class)
+ .getAdapter()
+ .getAttributionSource();
+ mTestDevice = getTestDevice(0);
+ }
+
+ @Test
+ public void connect() {
+ mBinder.connect(mTestDevice, mAttributionSource);
+ verify(mService).connect(mTestDevice);
+ }
+
+ @Test
+ public void disconnect() {
+ mBinder.disconnect(mTestDevice, mAttributionSource);
+ verify(mService).disconnect(mTestDevice);
+ }
+
+ @Test
+ public void getConnectedDevices() {
+ List<BluetoothDevice> connectedDevices = new ArrayList<>();
+ connectedDevices.add(mTestDevice);
+ when(mService.getConnectedDevices()).thenReturn(connectedDevices);
+
+ mBinder.getConnectedDevices(mAttributionSource);
+ verify(mService).getConnectedDevices();
+ }
+
+ @Test
+ public void getDevicesMatchingConnectionStates() {
+ int[] states = new int[] {STATE_CONNECTED, STATE_DISCONNECTED};
+ List<BluetoothDevice> devices = new ArrayList<>();
+ devices.add(mTestDevice);
+ when(mService.getDevicesMatchingConnectionStates(states)).thenReturn(devices);
+
+ mBinder.getDevicesMatchingConnectionStates(states, mAttributionSource);
+ verify(mService).getDevicesMatchingConnectionStates(states);
+ }
+
+ @Test
+ public void getConnectionState() {
+ when(mService.getConnectionState(mTestDevice)).thenReturn(STATE_CONNECTED);
+
+ mBinder.getConnectionState(mTestDevice, mAttributionSource);
+ verify(mService).getConnectionState(mTestDevice);
+ }
+
+ @Test
+ public void setActiveDevice() {
+ mBinder.setActiveDevice(mTestDevice, mAttributionSource);
+ verify(mService).setActiveDevice(mTestDevice);
+ }
+
+ @Test
+ public void removeActiveDevice() {
+ mBinder.setActiveDevice(null, mAttributionSource);
+ verify(mService).removeActiveDevice(false);
+ }
+
+ @Test
+ public void getActiveDevices() {
+ List<BluetoothDevice> activeDevices = new ArrayList<>();
+ activeDevices.add(mTestDevice);
+ when(mService.getActiveDevices()).thenReturn(activeDevices);
+
+ mBinder.getActiveDevices(mAttributionSource);
+ verify(mService).getActiveDevices();
+ }
+
+ @Test
+ public void setConnectionPolicy() {
+ mBinder.setConnectionPolicy(mTestDevice, CONNECTION_POLICY_ALLOWED, mAttributionSource);
+ verify(mService).setConnectionPolicy(mTestDevice, CONNECTION_POLICY_ALLOWED);
+ }
+
+ @Test
+ public void getConnectionPolicy() {
+ when(mService.getConnectionPolicy(mTestDevice)).thenReturn(CONNECTION_POLICY_FORBIDDEN);
+
+ mBinder.getConnectionPolicy(mTestDevice, mAttributionSource);
+ verify(mService).getConnectionPolicy(mTestDevice);
+ }
+
+ @Test
+ public void setVolume() {
+ int volume = 50;
+
+ mBinder.setVolume(volume, mAttributionSource);
+ verify(mService).setVolume(volume);
+ }
+
+ @Test
+ public void getHiSyncId() {
+ long hiSyncId = 1234567890L;
+ when(mService.getHiSyncId(mTestDevice)).thenReturn(hiSyncId);
+
+ mBinder.getHiSyncId(mTestDevice, mAttributionSource);
+ verify(mService).getHiSyncId(mTestDevice);
+ }
+
+ @Test
+ public void getDeviceSide() {
+ int side = BluetoothHearingAid.SIDE_LEFT;
+ when(mService.getCapabilities(mTestDevice)).thenReturn(side);
+
+ mBinder.getDeviceSide(mTestDevice, mAttributionSource);
+ verify(mService).getCapabilities(mTestDevice);
+ }
+
+ @Test
+ public void getDeviceMode() {
+ int mode = BluetoothHearingAid.MODE_BINAURAL;
+ when(mService.getCapabilities(mTestDevice)).thenReturn(mode << 1);
+
+ mBinder.getDeviceMode(mTestDevice, mAttributionSource);
+ verify(mService).getCapabilities(mTestDevice);
+ }
+
+ @Test
+ public void getAdvertisementServiceData() {
+ BluetoothHearingAid.AdvertisementServiceData data =
+ new BluetoothHearingAid.AdvertisementServiceData(0, 0);
+ when(mService.getAdvertisementServiceData(mTestDevice)).thenReturn(data);
+
+ mBinder.getAdvertisementServiceData(mTestDevice, mAttributionSource);
+ verify(mService).getAdvertisementServiceData(mTestDevice);
+ }
+
+ @Test
+ public void cleanup_doesNotCrash() {
+ mBinder.cleanup();
+ }
+}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceTest.java
index 757a6488be..a284d6a414 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceTest.java
@@ -97,7 +97,7 @@ public class HearingAidServiceTest {
private final BluetoothDevice mSingleDevice = getTestDevice(13);
private HearingAidService mService;
- private HearingAidService.BluetoothHearingAidBinder mBinder;
+ private HearingAidServiceBinder mBinder;
private InOrder mInOrder;
private TestLooper mLooper;
@@ -124,7 +124,7 @@ public class HearingAidServiceTest {
mService = new HearingAidService(mAdapterService, mLooper.getLooper(), mNativeInterface);
mService.setAvailable(true);
- mBinder = (HearingAidService.BluetoothHearingAidBinder) mService.initBinder();
+ mBinder = (HearingAidServiceBinder) mService.initBinder();
}
@After
diff --git a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/OWNERS b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/OWNERS
deleted file mode 100644
index bbaa85ddbb..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_hearingaid
diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java
index 3edd1ff9ea..835f03aaa2 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java
@@ -172,7 +172,9 @@ public class HeadsetServiceAndStateMachineTest {
doReturn(true).when(mNativeInterface).disconnectAudio(any(BluetoothDevice.class));
doReturn(true).when(mNativeInterface).setActiveDevice(any(BluetoothDevice.class));
doReturn(true).when(mNativeInterface).sendBsir(any(BluetoothDevice.class), anyBoolean());
- doReturn(true).when(mNativeInterface).startVoiceRecognition(any(BluetoothDevice.class));
+ doReturn(true)
+ .when(mNativeInterface)
+ .startVoiceRecognition(any(BluetoothDevice.class), anyBoolean());
doReturn(true).when(mNativeInterface).stopVoiceRecognition(any(BluetoothDevice.class));
doReturn(true)
.when(mNativeInterface)
@@ -1138,7 +1140,7 @@ public class HeadsetServiceAndStateMachineTest {
mTestLooper.dispatchAll();
verify(mNativeInterface).setActiveDevice(deviceA);
assertThat(mHeadsetService.getActiveDevice()).isEqualTo(deviceA);
- verify(mNativeInterface).startVoiceRecognition(deviceA);
+ verify(mNativeInterface).startVoiceRecognition(deviceA, true);
verify(mAudioManager).setA2dpSuspended(true);
verify(mAudioManager).setLeAudioSuspended(true);
verify(mNativeInterface).connectAudio(deviceA);
@@ -1685,6 +1687,7 @@ public class HeadsetServiceAndStateMachineTest {
// has not add verification AudioDeviceInfo because it is final, unless add a wrapper
mHeadsetService.startVoiceRecognition(device);
mTestLooper.dispatchAll();
+ verify(mNativeInterface).startVoiceRecognition(device, false);
verify(mAudioManager, times(0)).setA2dpSuspended(true);
verify(mAudioManager, times(0)).setLeAudioSuspended(true);
verify(mNativeInterface, times(0)).connectAudio(device);
@@ -1695,7 +1698,7 @@ public class HeadsetServiceAndStateMachineTest {
assertThat(device).isNotNull();
assertThat(mHeadsetService.startVoiceRecognition(device)).isTrue();
mTestLooper.dispatchAll();
- verify(mNativeInterface).startVoiceRecognition(device);
+ verify(mNativeInterface).startVoiceRecognition(device, true);
verify(mAudioManager).setA2dpSuspended(true);
verify(mAudioManager).setLeAudioSuspended(true);
verify(mNativeInterface).connectAudio(device);
@@ -1727,7 +1730,7 @@ public class HeadsetServiceAndStateMachineTest {
mHeadsetService.startVoiceRecognition(device);
mTestLooper.dispatchAll();
// has not add verification AudioDeviceInfo because it is final, unless add a wrapper
- verify(mNativeInterface).startVoiceRecognition(device);
+ verify(mNativeInterface).startVoiceRecognition(device, true);
verify(mAudioManager, times(0)).setA2dpSuspended(true);
verify(mAudioManager, times(0)).setLeAudioSuspended(true);
verify(mNativeInterface, times(0)).connectAudio(device);
diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/BluetoothHeadsetBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceBinderTest.java
index d125fbee4c..73f3610505 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/hfp/BluetoothHeadsetBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceBinderTest.java
@@ -27,12 +27,20 @@ import static org.mockito.Mockito.verify;
import android.bluetooth.BluetoothDevice;
import android.content.AttributionSource;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.Mock;
-public class BluetoothHeadsetBinderTest {
+/** Test cases for {@link HeadsetServiceBinder} */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class HeadsetServiceBinderTest {
+
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
@Mock private HeadsetService mService;
@@ -40,11 +48,11 @@ public class BluetoothHeadsetBinderTest {
private final AttributionSource mAttributionSource = new AttributionSource.Builder(1).build();
private final BluetoothDevice mDevice = getTestDevice(39);
- private HeadsetService.BluetoothHeadsetBinder mBinder;
+ private HeadsetServiceBinder mBinder;
@Before
public void setUp() throws Exception {
- mBinder = new HeadsetService.BluetoothHeadsetBinder(mService);
+ mBinder = new HeadsetServiceBinder(mService);
}
@Test
@@ -68,6 +76,7 @@ public class BluetoothHeadsetBinderTest {
@Test
public void getDevicesMatchingConnectionStates() {
int[] states = new int[] {STATE_CONNECTED};
+
mBinder.getDevicesMatchingConnectionStates(states, mAttributionSource);
verify(mService).getDevicesMatchingConnectionStates(states);
}
@@ -142,6 +151,7 @@ public class BluetoothHeadsetBinderTest {
@Test
public void setAudioRouteAllowed() {
boolean allowed = true;
+
mBinder.setAudioRouteAllowed(allowed, mAttributionSource);
verify(mService).setAudioRouteAllowed(allowed);
}
@@ -155,6 +165,7 @@ public class BluetoothHeadsetBinderTest {
@Test
public void setForceScoAudio() {
boolean forced = true;
+
mBinder.setForceScoAudio(forced, mAttributionSource);
verify(mService).setForceScoAudio(forced);
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceBinderTest.java
index b3171bc191..87f18055e5 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceBinderTest.java
@@ -25,6 +25,7 @@ import static com.android.bluetooth.TestUtils.getTestDevice;
import static org.mockito.Mockito.verify;
import android.bluetooth.BluetoothDevice;
+import android.content.AttributionSource;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -35,6 +36,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+/** Test cases for {@link HeadsetClientServiceBinder} */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class HeadsetClientServiceBinderTest {
@@ -42,32 +44,33 @@ public class HeadsetClientServiceBinderTest {
@Mock private HeadsetClientService mService;
+ private final AttributionSource mAttributionSource = new AttributionSource.Builder(1).build();
private final BluetoothDevice mDevice = getTestDevice(54);
- HeadsetClientService.BluetoothHeadsetClientBinder mBinder;
+ private HeadsetClientServiceBinder mBinder;
@Before
public void setUp() throws Exception {
- mBinder = new HeadsetClientService.BluetoothHeadsetClientBinder(mService);
+ mBinder = new HeadsetClientServiceBinder(mService);
}
@Test
public void connect_callsServiceMethod() {
- mBinder.connect(mDevice, null);
+ mBinder.connect(mDevice, mAttributionSource);
verify(mService).connect(mDevice);
}
@Test
public void disconnect_callsServiceMethod() {
- mBinder.disconnect(mDevice, null);
+ mBinder.disconnect(mDevice, mAttributionSource);
verify(mService).disconnect(mDevice);
}
@Test
public void getConnectedDevices_callsServiceMethod() {
- mBinder.getConnectedDevices(null);
+ mBinder.getConnectedDevices(mAttributionSource);
verify(mService).getConnectedDevices();
}
@@ -75,14 +78,14 @@ public class HeadsetClientServiceBinderTest {
@Test
public void getDevicesMatchingConnectionStates_callsServiceMethod() {
int[] states = new int[] {STATE_CONNECTED};
- mBinder.getDevicesMatchingConnectionStates(states, null);
+ mBinder.getDevicesMatchingConnectionStates(states, mAttributionSource);
verify(mService).getDevicesMatchingConnectionStates(states);
}
@Test
public void getConnectionState_callsServiceMethod() {
- mBinder.getConnectionState(mDevice, null);
+ mBinder.getConnectionState(mDevice, mAttributionSource);
verify(mService).getConnectionState(mDevice);
}
@@ -90,35 +93,35 @@ public class HeadsetClientServiceBinderTest {
@Test
public void setConnectionPolicy_callsServiceMethod() {
int connectionPolicy = CONNECTION_POLICY_ALLOWED;
- mBinder.setConnectionPolicy(mDevice, connectionPolicy, null);
+ mBinder.setConnectionPolicy(mDevice, connectionPolicy, mAttributionSource);
verify(mService).setConnectionPolicy(mDevice, connectionPolicy);
}
@Test
public void getConnectionPolicy_callsServiceMethod() {
- mBinder.getConnectionPolicy(mDevice, null);
+ mBinder.getConnectionPolicy(mDevice, mAttributionSource);
verify(mService).getConnectionPolicy(mDevice);
}
@Test
public void startVoiceRecognition_callsServiceMethod() {
- mBinder.startVoiceRecognition(mDevice, null);
+ mBinder.startVoiceRecognition(mDevice, mAttributionSource);
verify(mService).startVoiceRecognition(mDevice);
}
@Test
public void stopVoiceRecognition_callsServiceMethod() {
- mBinder.stopVoiceRecognition(mDevice, null);
+ mBinder.stopVoiceRecognition(mDevice, mAttributionSource);
verify(mService).stopVoiceRecognition(mDevice);
}
@Test
public void getAudioState_callsServiceMethod() {
- mBinder.getAudioState(mDevice, null);
+ mBinder.getAudioState(mDevice, mAttributionSource);
verify(mService).getAudioState(mDevice);
}
@@ -126,28 +129,28 @@ public class HeadsetClientServiceBinderTest {
@Test
public void setAudioRouteAllowed_callsServiceMethod() {
boolean allowed = true;
- mBinder.setAudioRouteAllowed(mDevice, allowed, null);
+ mBinder.setAudioRouteAllowed(mDevice, allowed, mAttributionSource);
verify(mService).setAudioRouteAllowed(mDevice, allowed);
}
@Test
public void getAudioRouteAllowed_callsServiceMethod() {
- mBinder.getAudioRouteAllowed(mDevice, null);
+ mBinder.getAudioRouteAllowed(mDevice, mAttributionSource);
verify(mService).getAudioRouteAllowed(mDevice);
}
@Test
public void connectAudio_callsServiceMethod() {
- mBinder.connectAudio(mDevice, null);
+ mBinder.connectAudio(mDevice, mAttributionSource);
verify(mService).connectAudio(mDevice);
}
@Test
public void disconnectAudio_callsServiceMethod() {
- mBinder.disconnectAudio(mDevice, null);
+ mBinder.disconnectAudio(mDevice, mAttributionSource);
verify(mService).disconnectAudio(mDevice);
}
@@ -155,35 +158,35 @@ public class HeadsetClientServiceBinderTest {
@Test
public void acceptCall_callsServiceMethod() {
int flag = 2;
- mBinder.acceptCall(mDevice, flag, null);
+ mBinder.acceptCall(mDevice, flag, mAttributionSource);
verify(mService).acceptCall(mDevice, flag);
}
@Test
public void rejectCall_callsServiceMethod() {
- mBinder.rejectCall(mDevice, null);
+ mBinder.rejectCall(mDevice, mAttributionSource);
verify(mService).rejectCall(mDevice);
}
@Test
public void holdCall_callsServiceMethod() {
- mBinder.holdCall(mDevice, null);
+ mBinder.holdCall(mDevice, mAttributionSource);
verify(mService).holdCall(mDevice);
}
@Test
public void terminateCall_callsServiceMethod() {
- mBinder.terminateCall(mDevice, null, null);
+ mBinder.terminateCall(mDevice, null, mAttributionSource);
verify(mService).terminateCall(mDevice, null);
}
@Test
public void explicitCallTransfer_callsServiceMethod() {
- mBinder.explicitCallTransfer(mDevice, null);
+ mBinder.explicitCallTransfer(mDevice, mAttributionSource);
verify(mService).explicitCallTransfer(mDevice);
}
@@ -191,7 +194,7 @@ public class HeadsetClientServiceBinderTest {
@Test
public void enterPrivateMode_callsServiceMethod() {
int index = 1;
- mBinder.enterPrivateMode(mDevice, index, null);
+ mBinder.enterPrivateMode(mDevice, index, mAttributionSource);
verify(mService).enterPrivateMode(mDevice, index);
}
@@ -199,7 +202,7 @@ public class HeadsetClientServiceBinderTest {
@Test
public void dial_callsServiceMethod() {
String number = "12532523";
- mBinder.dial(mDevice, number, null);
+ mBinder.dial(mDevice, number, mAttributionSource);
verify(mService).dial(mDevice, number);
}
@@ -207,21 +210,21 @@ public class HeadsetClientServiceBinderTest {
@Test
public void sendDTMF_callsServiceMethod() {
byte code = 21;
- mBinder.sendDTMF(mDevice, code, null);
+ mBinder.sendDTMF(mDevice, code, mAttributionSource);
verify(mService).sendDTMF(mDevice, code);
}
@Test
public void getLastVoiceTagNumber_callsServiceMethod() {
- mBinder.getLastVoiceTagNumber(mDevice, null);
+ mBinder.getLastVoiceTagNumber(mDevice, mAttributionSource);
verify(mService).getLastVoiceTagNumber(mDevice);
}
@Test
public void getCurrentAgEvents_callsServiceMethod() {
- mBinder.getCurrentAgEvents(mDevice, null);
+ mBinder.getCurrentAgEvents(mDevice, mAttributionSource);
verify(mService).getCurrentAgEvents(mDevice);
}
@@ -231,14 +234,14 @@ public class HeadsetClientServiceBinderTest {
int vendorId = 5;
String cmd = "test_command";
- mBinder.sendVendorAtCommand(mDevice, vendorId, cmd, null);
+ mBinder.sendVendorAtCommand(mDevice, vendorId, cmd, mAttributionSource);
verify(mService).sendVendorAtCommand(mDevice, vendorId, cmd);
}
@Test
public void getCurrentAgFeatures_callsServiceMethod() {
- mBinder.getCurrentAgFeatures(mDevice, null);
+ mBinder.getCurrentAgFeatures(mDevice, mAttributionSource);
verify(mService).getCurrentAgFeaturesBundle(mDevice);
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/BluetoothHidDeviceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceServiceBinderTest.java
index 8a03fe7186..4369e85310 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/hid/BluetoothHidDeviceBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceServiceBinderTest.java
@@ -33,12 +33,20 @@ import android.bluetooth.BluetoothHidDeviceAppSdpSettings;
import android.bluetooth.IBluetoothHidDeviceCallback;
import android.content.AttributionSource;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.Mock;
-public class BluetoothHidDeviceBinderTest {
+/** Test cases for {@link HidDeviceServiceBinder} */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class HidDeviceServiceBinderTest {
+
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
@Mock private HidDeviceService mService;
@@ -46,12 +54,12 @@ public class BluetoothHidDeviceBinderTest {
private final AttributionSource mAttributionSource = new AttributionSource.Builder(1).build();
private final BluetoothDevice mDevice = getTestDevice(29);
- private HidDeviceService.BluetoothHidDeviceBinder mBinder;
+ private HidDeviceServiceBinder mBinder;
@Before
public void setUp() throws Exception {
when(mService.isAvailable()).thenReturn(true);
- mBinder = new HidDeviceService.BluetoothHidDeviceBinder(mService);
+ mBinder = new HidDeviceServiceBinder(mService);
}
@Test
diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceServiceTest.java
index 5ddb36e4c6..a242f054a7 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceServiceTest.java
@@ -76,7 +76,7 @@ import org.mockito.hamcrest.MockitoHamcrest;
@MediumTest
@RunWith(AndroidJUnit4.class)
-public class HidDeviceTest {
+public class HidDeviceServiceTest {
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
@Mock private AdapterService mAdapterService;
diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java
index 02bee889e8..2c393118bb 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java
@@ -25,6 +25,7 @@ import static com.android.bluetooth.TestUtils.getTestDevice;
import static org.mockito.Mockito.verify;
import android.bluetooth.BluetoothDevice;
+import android.content.AttributionSource;
import android.platform.test.flag.junit.SetFlagsRule;
import androidx.test.filters.SmallTest;
@@ -36,108 +37,103 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+/** Test cases for {@link HidHostServiceBinder}. */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class HidHostServiceBinderTest {
+
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
@Mock private HidHostService mService;
+ private final AttributionSource mAttributionSource = new AttributionSource.Builder(1).build();
private final BluetoothDevice mDevice = getTestDevice(50);
- private HidHostService.BluetoothHidHostBinder mBinder;
+ private HidHostServiceBinder mBinder;
@Before
public void setUp() {
- mBinder = new HidHostService.BluetoothHidHostBinder(mService);
+ mBinder = new HidHostServiceBinder(mService);
}
@Test
public void connect_callsServiceMethod() {
- mBinder.connect(mDevice, null);
-
+ mBinder.connect(mDevice, mAttributionSource);
verify(mService).connect(mDevice);
}
@Test
public void disconnect_callsServiceMethod() {
- mBinder.disconnect(mDevice, null);
-
+ mBinder.disconnect(mDevice, mAttributionSource);
verify(mService).disconnect(mDevice);
}
@Test
public void getConnectedDevices_callsServiceMethod() {
- mBinder.getConnectedDevices(null);
-
+ mBinder.getConnectedDevices(mAttributionSource);
verify(mService).getDevicesMatchingConnectionStates(new int[] {STATE_CONNECTED});
}
@Test
public void getDevicesMatchingConnectionStates_callsServiceMethod() {
int[] states = new int[] {STATE_CONNECTED};
- mBinder.getDevicesMatchingConnectionStates(states, null);
+ mBinder.getDevicesMatchingConnectionStates(states, mAttributionSource);
verify(mService).getDevicesMatchingConnectionStates(states);
}
@Test
public void getConnectionState_callsServiceMethod() {
- mBinder.getConnectionState(mDevice, null);
-
+ mBinder.getConnectionState(mDevice, mAttributionSource);
verify(mService).getConnectionState(mDevice);
}
@Test
public void setConnectionPolicy_callsServiceMethod() {
int connectionPolicy = CONNECTION_POLICY_ALLOWED;
- mBinder.setConnectionPolicy(mDevice, connectionPolicy, null);
+ mBinder.setConnectionPolicy(mDevice, connectionPolicy, mAttributionSource);
verify(mService).setConnectionPolicy(mDevice, connectionPolicy);
}
@Test
public void getConnectionPolicy_callsServiceMethod() {
- mBinder.getConnectionPolicy(mDevice, null);
-
+ mBinder.getConnectionPolicy(mDevice, mAttributionSource);
verify(mService).getConnectionPolicy(mDevice);
}
@Test
public void setPreferredTransport_callsServiceMethod() {
int preferredTransport = BluetoothDevice.TRANSPORT_AUTO;
- mBinder.setPreferredTransport(mDevice, preferredTransport, null);
+ mBinder.setPreferredTransport(mDevice, preferredTransport, mAttributionSource);
verify(mService).setPreferredTransport(mDevice, preferredTransport);
}
@Test
public void getPreferredTransport_callsServiceMethod() {
- mBinder.getPreferredTransport(mDevice, null);
-
+ mBinder.getPreferredTransport(mDevice, mAttributionSource);
verify(mService).getPreferredTransport(mDevice);
}
@Test
public void getProtocolMode_callsServiceMethod() {
- mBinder.getProtocolMode(mDevice, null);
-
+ mBinder.getProtocolMode(mDevice, mAttributionSource);
verify(mService).getProtocolMode(mDevice);
}
@Test
public void virtualUnplug_callsServiceMethod() {
- mBinder.virtualUnplug(mDevice, null);
-
+ mBinder.virtualUnplug(mDevice, mAttributionSource);
verify(mService).virtualUnplug(mDevice);
}
@Test
public void setProtocolMode_callsServiceMethod() {
int protocolMode = 1;
- mBinder.setProtocolMode(mDevice, protocolMode, null);
+ mBinder.setProtocolMode(mDevice, protocolMode, mAttributionSource);
verify(mService).setProtocolMode(mDevice, protocolMode);
}
@@ -146,8 +142,8 @@ public class HidHostServiceBinderTest {
byte reportType = 1;
byte reportId = 2;
int bufferSize = 16;
- mBinder.getReport(mDevice, reportType, reportId, bufferSize, null);
+ mBinder.getReport(mDevice, reportType, reportId, bufferSize, mAttributionSource);
verify(mService).getReport(mDevice, reportType, reportId, bufferSize);
}
@@ -155,31 +151,30 @@ public class HidHostServiceBinderTest {
public void setReport_callsServiceMethod() {
byte reportType = 1;
String report = "test_report";
- mBinder.setReport(mDevice, reportType, report, null);
+ mBinder.setReport(mDevice, reportType, report, mAttributionSource);
verify(mService).setReport(mDevice, reportType, report);
}
@Test
public void sendData_callsServiceMethod() {
String report = "test_report";
- mBinder.sendData(mDevice, report, null);
+ mBinder.sendData(mDevice, report, mAttributionSource);
verify(mService).sendData(mDevice, report);
}
@Test
public void setIdleTime_callsServiceMethod() {
byte idleTime = 1;
- mBinder.setIdleTime(mDevice, idleTime, null);
+ mBinder.setIdleTime(mDevice, idleTime, mAttributionSource);
verify(mService).setIdleTime(mDevice, idleTime);
}
@Test
public void getIdleTime_callsServiceMethod() {
- mBinder.getIdleTime(mDevice, null);
-
+ mBinder.getIdleTime(mDevice, mAttributionSource);
verify(mService).getIdleTime(mDevice);
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java
index a41f93d5d6..10f5f3257f 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.bluetooth.hid;
import static android.bluetooth.BluetoothDevice.BOND_BONDED;
@@ -53,6 +54,7 @@ import java.util.List;
@MediumTest
@RunWith(AndroidJUnit4.class)
public class HidHostServiceTest {
+
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
@Mock private AdapterService mAdapterService;
diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceBinderTest.java
index 15b3563df1..68677ffedb 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceBinderTest.java
@@ -36,15 +36,23 @@ import android.content.AttributionSource;
import android.os.ParcelUuid;
import android.platform.test.flag.junit.SetFlagsRule;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import java.util.UUID;
-public class LeAudioBinderTest {
+/** Test cases for {@link LeAudioServiceBinder} */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class LeAudioServiceBinderTest {
+
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
@@ -53,11 +61,11 @@ public class LeAudioBinderTest {
private static final String TEST_BROADCAST_NAME = "TEST";
private static final int TEST_QUALITY = BluetoothLeBroadcastSubgroupSettings.QUALITY_STANDARD;
- private LeAudioService.BluetoothLeAudioBinder mBinder;
+ private LeAudioServiceBinder mBinder;
@Before
public void setUp() {
- mBinder = new LeAudioService.BluetoothLeAudioBinder(mService);
+ mBinder = new LeAudioServiceBinder(mService);
}
@Test
diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java
index f0f2037358..cf836ddc3c 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java
@@ -76,12 +76,12 @@ import android.os.ParcelUuid;
import android.os.RemoteException;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.FlagsParameterization;
import android.platform.test.flag.junit.SetFlagsRule;
import android.sysprop.BluetoothProperties;
import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
import com.android.bluetooth.TestUtils;
import com.android.bluetooth.bass_client.BassClientService;
@@ -113,15 +113,20 @@ import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.hamcrest.MockitoHamcrest;
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
@MediumTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(ParameterizedAndroidJunit4.class)
public class LeAudioServiceTest {
- @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+ @Rule public final SetFlagsRule mSetFlagsRule;
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
@Mock private AdapterService mAdapterService;
@@ -201,6 +206,20 @@ public class LeAudioServiceTest {
private InOrder mInOrder;
+ @Parameters(name = "{0}")
+ public static List<FlagsParameterization> getParams() {
+ return FlagsParameterization.progressionOf(
+ Flags.FLAG_LEAUDIO_BROADCAST_PRIMARY_GROUP_SELECTION,
+ Flags.FLAG_LEAUDIO_CODEC_CONFIG_CALLBACK_ORDER_FIX,
+ Flags.FLAG_LEAUDIO_UNICAST_NO_AVAILABLE_CONTEXTS,
+ Flags.FLAG_LEAUDIO_BROADCAST_API_MANAGE_PRIMARY_GROUP,
+ Flags.FLAG_DO_NOT_HARDCODE_TMAP_ROLE_MASK);
+ }
+
+ public LeAudioServiceTest(FlagsParameterization flags) {
+ mSetFlagsRule = new SetFlagsRule(flags);
+ }
+
@Before
public void setUp() throws Exception {
mInOrder = inOrder(mAdapterService);
@@ -211,11 +230,9 @@ public class LeAudioServiceTest {
doReturn(mTargetContext.getContentResolver()).when(mAdapterService).getContentResolver();
doReturn(MAX_LE_AUDIO_CONNECTIONS).when(mAdapterService).getMaxConnectedAudioDevices();
- doReturn(
- (long) (1 << BluetoothProfile.LE_AUDIO_BROADCAST)
- | (1 << BluetoothProfile.LE_AUDIO))
- .when(mAdapterService)
- .getSupportedProfilesBitMask();
+ injectSupportedProfilesBitMask(
+ Set.of(BluetoothProfile.LE_AUDIO_BROADCAST, BluetoothProfile.LE_AUDIO));
+
doReturn(new ParcelUuid[] {BluetoothUuid.LE_AUDIO})
.when(mAdapterService)
.getRemoteUuids(any(BluetoothDevice.class));
@@ -280,6 +297,43 @@ public class LeAudioServiceTest {
assertThat(LeAudioService.getLeAudioService()).isNull();
}
+ @Test
+ @EnableFlags(Flags.FLAG_DO_NOT_HARDCODE_TMAP_ROLE_MASK)
+ public void testTmapRoleMask() {
+ List<Set<Integer>> powerSet =
+ List.of(
+ Set.of(BluetoothProfile.LE_CALL_CONTROL),
+ Set.of(BluetoothProfile.MCP_SERVER),
+ Set.of(BluetoothProfile.LE_CALL_CONTROL, BluetoothProfile.MCP_SERVER),
+ Set.of(BluetoothProfile.LE_AUDIO_BROADCAST),
+ Set.of(
+ BluetoothProfile.LE_AUDIO_BROADCAST,
+ BluetoothProfile.LE_CALL_CONTROL),
+ Set.of(BluetoothProfile.LE_AUDIO_BROADCAST, BluetoothProfile.MCP_SERVER),
+ Set.of(
+ BluetoothProfile.LE_AUDIO_BROADCAST,
+ BluetoothProfile.LE_CALL_CONTROL,
+ BluetoothProfile.MCP_SERVER));
+
+ List<Integer> tmapMasks =
+ powerSet.stream()
+ .map(
+ set -> {
+ injectSupportedProfilesBitMask(set);
+ LeAudioService service =
+ new LeAudioService(mAdapterService, mNativeInterface);
+ return service.getTmapRoleMask();
+ })
+ .collect(Collectors.toList());
+
+ List<Integer> expectedMasks =
+ powerSet.stream()
+ .map(LeAudioServiceTest::constructTmapRoleMask)
+ .collect(Collectors.toList());
+
+ assertThat(tmapMasks).containsExactly(expectedMasks.toArray()).inOrder();
+ }
+
/** Test getting LeAudio Service: getLeAudioService() */
@Test
public void testGetLeAudioService() {
@@ -1788,8 +1842,8 @@ public class LeAudioServiceTest {
/** Test native interface group status message handling */
@Test
+ @EnableFlags(Flags.FLAG_LEAUDIO_CODEC_CONFIG_CALLBACK_ORDER_FIX)
public void testMessageFromNativeGroupCodecConfigChangedNonActiveDevice() {
- mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_CODEC_CONFIG_CALLBACK_ORDER_FIX);
onGroupCodecConfChangedCallbackCalled = false;
injectLocalCodecConfigCapaChanged(INPUT_CAPABILITIES_CONFIG, OUTPUT_CAPABILITIES_CONFIG);
@@ -1874,8 +1928,8 @@ public class LeAudioServiceTest {
/** Test native interface group status message handling */
@Test
+ @EnableFlags(Flags.FLAG_LEAUDIO_CODEC_CONFIG_CALLBACK_ORDER_FIX)
public void testMessageFromNativeGroupCodecConfigChangedActiveDevice_DifferentConfiguration() {
- mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_CODEC_CONFIG_CALLBACK_ORDER_FIX);
onGroupCodecConfChangedCallbackCalled = false;
injectLocalCodecConfigCapaChanged(INPUT_CAPABILITIES_CONFIG, OUTPUT_CAPABILITIES_CONFIG);
@@ -3216,4 +3270,30 @@ public class LeAudioServiceTest {
.sendBroadcastAsUser(
MockitoHamcrest.argThat(AllOf.allOf(matchers)), any(), any(), any());
}
+
+ private void injectSupportedProfilesBitMask(Set<Integer> profiles) {
+ long mask = 0;
+ for (int profile : profiles) {
+ mask |= (long) (1 << profile);
+ }
+ doReturn(mask).when(mAdapterService).getSupportedProfilesBitMask();
+ }
+
+ private static int constructTmapRoleMask(Set<Integer> profiles) {
+ int mask = 0;
+ for (int profile : profiles) {
+ switch (profile) {
+ case BluetoothProfile.LE_CALL_CONTROL:
+ mask |= LeAudioTmapGattServer.TMAP_ROLE_FLAG_CG;
+ break;
+ case BluetoothProfile.MCP_SERVER:
+ mask |= LeAudioTmapGattServer.TMAP_ROLE_FLAG_UMS;
+ break;
+ case BluetoothProfile.LE_AUDIO_BROADCAST:
+ mask |= LeAudioTmapGattServer.TMAP_ROLE_FLAG_BMS;
+ break;
+ }
+ }
+ return mask;
+ }
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/OWNERS b/android/app/tests/unit/src/com/android/bluetooth/le_audio/OWNERS
deleted file mode 100644
index a7d77894ba..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_leaudio
diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanBinderTest.java
deleted file mode 100644
index 61c7df48b8..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanBinderTest.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2025 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.bluetooth.le_scan;
-
-import static com.android.bluetooth.TestUtils.MockitoRule;
-import static com.android.bluetooth.TestUtils.getTestDevice;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import android.app.PendingIntent;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothManager;
-import android.bluetooth.le.IPeriodicAdvertisingCallback;
-import android.bluetooth.le.IScannerCallback;
-import android.bluetooth.le.ScanFilter;
-import android.bluetooth.le.ScanResult;
-import android.bluetooth.le.ScanSettings;
-import android.content.AttributionSource;
-import android.content.Intent;
-import android.os.WorkSource;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/** Test cases for {@link ScanBinder}. */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class ScanBinderTest {
- @Rule public final MockitoRule mMockitoRule = new MockitoRule();
-
- @Mock private ScanController mScanController;
-
- private final AttributionSource mAttributionSource =
- InstrumentationRegistry.getInstrumentation()
- .getTargetContext()
- .getSystemService(BluetoothManager.class)
- .getAdapter()
- .getAttributionSource();
- private final BluetoothDevice mDevice = getTestDevice(89);
- private ScanBinder mBinder;
-
- @Before
- public void setUp() {
- mBinder = new ScanBinder(mScanController);
- }
-
- @Test
- public void registerScanner() {
- IScannerCallback callback = mock(IScannerCallback.class);
- WorkSource workSource = mock(WorkSource.class);
-
- mBinder.registerScanner(callback, workSource, mAttributionSource);
- verify(mScanController).registerScanner(callback, workSource, mAttributionSource);
- }
-
- @Test
- public void unregisterScanner() {
- int scannerId = 1;
-
- mBinder.unregisterScanner(scannerId, mAttributionSource);
- verify(mScanController).unregisterScanner(scannerId, mAttributionSource);
- }
-
- @Test
- public void startScan() {
- int scannerId = 1;
- ScanSettings settings = new ScanSettings.Builder().build();
- List<ScanFilter> filters = new ArrayList<>();
-
- mBinder.startScan(scannerId, settings, filters, mAttributionSource);
- verify(mScanController).startScan(scannerId, settings, filters, mAttributionSource);
- }
-
- @Test
- public void startScanForIntent() {
- PendingIntent intent =
- PendingIntent.getBroadcast(
- InstrumentationRegistry.getInstrumentation().getTargetContext(),
- 0,
- new Intent(),
- PendingIntent.FLAG_IMMUTABLE);
- ScanSettings settings = new ScanSettings.Builder().build();
- List<ScanFilter> filters = new ArrayList<>();
-
- mBinder.startScanForIntent(intent, settings, filters, mAttributionSource);
- verify(mScanController)
- .registerPiAndStartScan(intent, settings, filters, mAttributionSource);
- }
-
- @Test
- public void stopScan_withScannerId() {
- int scannerId = 1;
-
- mBinder.stopScan(scannerId, mAttributionSource);
- verify(mScanController).stopScan(scannerId, mAttributionSource);
- }
-
- @Test
- public void stopScan_withIntent() {
- PendingIntent intent =
- PendingIntent.getBroadcast(
- InstrumentationRegistry.getInstrumentation().getTargetContext(),
- 0,
- new Intent(),
- PendingIntent.FLAG_IMMUTABLE);
-
- mBinder.stopScanForIntent(intent, mAttributionSource);
- verify(mScanController).stopScan(intent, mAttributionSource);
- }
-
- @Test
- public void flushPendingBatchResults() {
- int scannerId = 1;
-
- mBinder.flushPendingBatchResults(scannerId, mAttributionSource);
- verify(mScanController).flushPendingBatchResults(scannerId, mAttributionSource);
- }
-
- @Test
- public void registerSync() {
- ScanResult scanResult = new ScanResult(mDevice, null, 0, 0);
- int skip = 1;
- int timeout = 2;
- IPeriodicAdvertisingCallback callback = mock(IPeriodicAdvertisingCallback.class);
-
- mBinder.registerSync(scanResult, skip, timeout, callback, mAttributionSource);
- verify(mScanController)
- .registerSync(scanResult, skip, timeout, callback, mAttributionSource);
- }
-
- @Test
- public void unregisterSync() {
- IPeriodicAdvertisingCallback callback = mock(IPeriodicAdvertisingCallback.class);
-
- mBinder.unregisterSync(callback, mAttributionSource);
- verify(mScanController).unregisterSync(callback, mAttributionSource);
- }
-
- @Test
- public void transferSync() {
- int serviceData = 1;
- int syncHandle = 2;
-
- mBinder.transferSync(mDevice, serviceData, syncHandle, mAttributionSource);
- verify(mScanController).transferSync(mDevice, serviceData, syncHandle, mAttributionSource);
- }
-
- @Test
- public void transferSetInfo() {
- int serviceData = 1;
- int advHandle = 2;
- IPeriodicAdvertisingCallback callback = mock(IPeriodicAdvertisingCallback.class);
-
- mBinder.transferSetInfo(mDevice, serviceData, advHandle, callback, mAttributionSource);
- verify(mScanController)
- .transferSetInfo(mDevice, serviceData, advHandle, callback, mAttributionSource);
- }
-
- @Test
- public void numHwTrackFiltersAvailable() {
- mBinder.numHwTrackFiltersAvailable(mAttributionSource);
- verify(mScanController).numHwTrackFiltersAvailable(mAttributionSource);
- }
-
- @Test
- public void cleanup_doesNotCrash() {
- mBinder.cleanup();
- }
-}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanBinderTest.kt b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanBinderTest.kt
new file mode 100644
index 0000000000..3424c48a54
--- /dev/null
+++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanBinderTest.kt
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.le_scan
+
+import android.app.PendingIntent
+import android.bluetooth.BluetoothDevice
+import android.bluetooth.BluetoothManager
+import android.bluetooth.le.IPeriodicAdvertisingCallback
+import android.bluetooth.le.IScannerCallback
+import android.bluetooth.le.ScanFilter
+import android.bluetooth.le.ScanResult
+import android.bluetooth.le.ScanSettings
+import android.content.Intent
+import android.os.WorkSource
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.bluetooth.TestUtils.MockitoRule
+import com.android.bluetooth.TestUtils.getTestDevice
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.verify
+
+/** Test cases for [ScanBinder] */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ScanBinderTest {
+
+ @get:Rule val mockitoRule = MockitoRule()
+
+ @Mock private lateinit var scanController: ScanController
+
+ private val attributionSource =
+ InstrumentationRegistry.getInstrumentation()
+ .targetContext
+ .getSystemService(BluetoothManager::class.java)
+ .adapter
+ .attributionSource
+ private val device: BluetoothDevice = getTestDevice(89)
+ private lateinit var binder: ScanBinder
+
+ @Before
+ fun setUp() {
+ binder = ScanBinder(scanController)
+ }
+
+ @Test
+ fun registerScanner() {
+ val callback = mock(IScannerCallback::class.java)
+ val workSource = mock(WorkSource::class.java)
+
+ binder.registerScanner(callback, workSource, attributionSource)
+ verify(scanController).registerScanner(callback, workSource, attributionSource)
+ }
+
+ @Test
+ fun unregisterScanner() {
+ val scannerId = 1
+
+ binder.unregisterScanner(scannerId, attributionSource)
+ verify(scanController).unregisterScanner(scannerId, attributionSource)
+ }
+
+ @Test
+ fun startScan() {
+ val scannerId = 1
+ val settings = ScanSettings.Builder().build()
+ val filters = listOf<ScanFilter>()
+
+ binder.startScan(scannerId, settings, filters, attributionSource)
+ verify(scanController).startScan(scannerId, settings, filters, attributionSource)
+ }
+
+ @Test
+ fun startScanForIntent() {
+ val intent =
+ PendingIntent.getBroadcast(
+ InstrumentationRegistry.getInstrumentation().targetContext,
+ 0,
+ Intent(),
+ PendingIntent.FLAG_IMMUTABLE,
+ )
+ val settings = ScanSettings.Builder().build()
+ val filters = listOf<ScanFilter>()
+
+ binder.startScanForIntent(intent, settings, filters, attributionSource)
+ verify(scanController).registerPiAndStartScan(intent, settings, filters, attributionSource)
+ }
+
+ @Test
+ fun stopScan_withScannerId() {
+ val scannerId = 1
+
+ binder.stopScan(scannerId, attributionSource)
+ verify(scanController).stopScan(scannerId, attributionSource)
+ }
+
+ @Test
+ fun stopScan_withIntent() {
+ val intent =
+ PendingIntent.getBroadcast(
+ InstrumentationRegistry.getInstrumentation().targetContext,
+ 0,
+ Intent(),
+ PendingIntent.FLAG_IMMUTABLE,
+ )
+
+ binder.stopScanForIntent(intent, attributionSource)
+ verify(scanController).stopScan(intent, attributionSource)
+ }
+
+ @Test
+ fun flushPendingBatchResults() {
+ val scannerId = 1
+
+ binder.flushPendingBatchResults(scannerId, attributionSource)
+ verify(scanController).flushPendingBatchResults(scannerId, attributionSource)
+ }
+
+ @Test
+ fun registerSync() {
+ val scanResult = mock(ScanResult::class.java)
+ val skip = 1
+ val timeout = 2
+ val callback = mock(IPeriodicAdvertisingCallback::class.java)
+
+ binder.registerSync(scanResult, skip, timeout, callback, attributionSource)
+ verify(scanController).registerSync(scanResult, skip, timeout, callback, attributionSource)
+ }
+
+ @Test
+ fun unregisterSync() {
+ val callback = mock(IPeriodicAdvertisingCallback::class.java)
+
+ binder.unregisterSync(callback, attributionSource)
+ verify(scanController).unregisterSync(callback, attributionSource)
+ }
+
+ @Test
+ fun transferSync() {
+ val serviceData = 1
+ val syncHandle = 2
+
+ binder.transferSync(device, serviceData, syncHandle, attributionSource)
+ verify(scanController).transferSync(device, serviceData, syncHandle, attributionSource)
+ }
+
+ @Test
+ fun transferSetInfo() {
+ val serviceData = 1
+ val advHandle = 2
+ val callback = mock(IPeriodicAdvertisingCallback::class.java)
+
+ binder.transferSetInfo(device, serviceData, advHandle, callback, attributionSource)
+ verify(scanController)
+ .transferSetInfo(device, serviceData, advHandle, callback, attributionSource)
+ }
+
+ @Test
+ fun numHwTrackFiltersAvailable() {
+ binder.numHwTrackFiltersAvailable(attributionSource)
+ verify(scanController).numHwTrackFiltersAvailable(attributionSource)
+ }
+
+ @Test
+ fun cleanup_doesNotCrash() {
+ binder.cleanup()
+ }
+}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanManagerTest.java
index 22d8fed0ac..54a3679ee6 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanManagerTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanManagerTest.java
@@ -1227,7 +1227,6 @@ public class ScanManagerTest {
}
@Test
- @EnableFlags(Flags.FLAG_BLE_SCAN_ADV_METRICS_REDESIGN)
public void testMetricsAppScanScreenOn() {
// Set filtered scan flag
final boolean isFiltered = true;
@@ -1292,7 +1291,8 @@ public class ScanManagerTest {
0,
true,
false,
- IMPORTANCE_FOREGROUND_SERVICE);
+ IMPORTANCE_FOREGROUND_SERVICE,
+ "");
advanceTime(scanTestDuration);
// Record scan stop
@@ -1317,12 +1317,12 @@ public class ScanManagerTest {
eq(0),
eq(true),
eq(false),
- eq(IMPORTANCE_FOREGROUND_SERVICE));
+ eq(IMPORTANCE_FOREGROUND_SERVICE),
+ eq(""));
}
}
@Test
- @EnableFlags(Flags.FLAG_BLE_SCAN_ADV_METRICS_REDESIGN)
public void testMetricsRadioScanScreenOnOffMultiScan() {
// Set filtered scan flag
final boolean isFiltered = true;
@@ -1390,7 +1390,8 @@ public class ScanManagerTest {
eq((long) ScanManager.SCAN_MODE_LOW_POWER_WINDOW_MS),
eq(true),
eq(scanTestDuration),
- eq(IMPORTANCE_FOREGROUND_SERVICE));
+ eq(IMPORTANCE_FOREGROUND_SERVICE),
+ eq(""));
advanceTime(scanTestDuration);
// Create workSource for the third app
@@ -1430,7 +1431,8 @@ public class ScanManagerTest {
eq((long) ScanManager.SCAN_MODE_BALANCED_WINDOW_MS),
eq(true),
eq(scanTestDuration),
- eq(IMPORTANCE_FOREGROUND_SERVICE));
+ eq(IMPORTANCE_FOREGROUND_SERVICE),
+ eq(""));
advanceTime(scanTestDuration);
// Create workSource for the fourth app
@@ -1467,7 +1469,8 @@ public class ScanManagerTest {
anyLong(),
anyBoolean(),
anyLong(),
- anyInt());
+ anyInt(),
+ eq(""));
advanceTime(scanTestDuration);
// Set as background app
@@ -1492,7 +1495,8 @@ public class ScanManagerTest {
eq((long) ScanManager.SCAN_MODE_LOW_LATENCY_WINDOW_MS),
eq(true),
eq(scanTestDuration * 2),
- eq(IMPORTANCE_FOREGROUND_SERVICE));
+ eq(IMPORTANCE_FOREGROUND_SERVICE),
+ eq(""));
advanceTime(scanTestDuration);
// Get the most aggressive scan client when screen is off
@@ -1521,7 +1525,8 @@ public class ScanManagerTest {
eq((long) SCAN_MODE_SCREEN_OFF_LOW_POWER_WINDOW_MS),
eq(false),
eq(scanTestDuration),
- eq(IMPORTANCE_FOREGROUND_SERVICE + 1));
+ eq(IMPORTANCE_FOREGROUND_SERVICE + 1),
+ eq(""));
advanceTime(scanTestDuration);
// Stop scan for the fourth app
@@ -1538,7 +1543,8 @@ public class ScanManagerTest {
anyLong(),
anyBoolean(),
anyLong(),
- anyInt());
+ anyInt(),
+ eq(""));
advanceTime(scanTestDuration);
// Stop scan for the third app
@@ -1558,7 +1564,8 @@ public class ScanManagerTest {
eq((long) ScanManager.SCAN_MODE_LOW_LATENCY_WINDOW_MS),
eq(true),
eq(scanTestDuration * 2),
- eq(IMPORTANCE_FOREGROUND_SERVICE));
+ eq(IMPORTANCE_FOREGROUND_SERVICE),
+ eq(""));
advanceTime(scanTestDuration);
// Stop scan for the second app
@@ -1578,7 +1585,8 @@ public class ScanManagerTest {
eq((long) ScanManager.SCAN_MODE_BALANCED_WINDOW_MS),
eq(true),
eq(scanTestDuration),
- eq(IMPORTANCE_FOREGROUND_SERVICE));
+ eq(IMPORTANCE_FOREGROUND_SERVICE),
+ eq(""));
advanceTime(scanTestDuration);
// Stop scan for the first app
@@ -1598,7 +1606,8 @@ public class ScanManagerTest {
eq((long) ScanManager.SCAN_MODE_LOW_POWER_WINDOW_MS),
eq(true),
eq(scanTestDuration),
- eq(IMPORTANCE_FOREGROUND_SERVICE));
+ eq(IMPORTANCE_FOREGROUND_SERVICE),
+ eq(""));
}
@Test
diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceBinderTest.java
index fa0c3d3f35..0ebb4e7bd2 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceBinderTest.java
@@ -25,6 +25,7 @@ import static com.android.bluetooth.TestUtils.getTestDevice;
import static org.mockito.Mockito.verify;
import android.bluetooth.BluetoothDevice;
+import android.content.AttributionSource;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -35,88 +36,85 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+/** Test cases for {@link BluetoothMapServiceBinder} */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class BluetoothMapServiceBinderTest {
+
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
@Mock private BluetoothMapService mService;
+ private final AttributionSource mAttributionSource = new AttributionSource.Builder(1).build();
private final BluetoothDevice mDevice = getTestDevice(98);
- private BluetoothMapService.BluetoothMapBinder mBinder;
+ private BluetoothMapServiceBinder mBinder;
@Before
public void setUp() throws Exception {
- mBinder = new BluetoothMapService.BluetoothMapBinder(mService);
+ mBinder = new BluetoothMapServiceBinder(mService);
}
@Test
public void disconnect_callsServiceMethod() {
- mBinder.disconnect(mDevice, null);
-
+ mBinder.disconnect(mDevice, mAttributionSource);
verify(mService).disconnect(mDevice);
}
@Test
public void getConnectedDevices_callsServiceMethod() {
- mBinder.getConnectedDevices(null);
-
+ mBinder.getConnectedDevices(mAttributionSource);
verify(mService).getConnectedDevices();
}
@Test
public void getDevicesMatchingConnectionStates_callsServiceMethod() {
int[] states = new int[] {STATE_CONNECTED};
- mBinder.getDevicesMatchingConnectionStates(states, null);
+ mBinder.getDevicesMatchingConnectionStates(states, mAttributionSource);
verify(mService).getDevicesMatchingConnectionStates(states);
}
@Test
public void getConnectionState_callsServiceMethod() {
- mBinder.getConnectionState(mDevice, null);
-
+ mBinder.getConnectionState(mDevice, mAttributionSource);
verify(mService).getConnectionState(mDevice);
}
@Test
public void setConnectionPolicy_callsServiceMethod() {
int connectionPolicy = CONNECTION_POLICY_ALLOWED;
- mBinder.setConnectionPolicy(mDevice, connectionPolicy, null);
+ mBinder.setConnectionPolicy(mDevice, connectionPolicy, mAttributionSource);
verify(mService).setConnectionPolicy(mDevice, connectionPolicy);
}
@Test
public void getConnectionPolicy_callsServiceMethod() {
- mBinder.getConnectionPolicy(mDevice, null);
-
+ mBinder.getConnectionPolicy(mDevice, mAttributionSource);
verify(mService).getConnectionPolicy(mDevice);
}
@Test
public void getState_callsServiceMethod() {
- mBinder.getState(null);
-
+ mBinder.getState(mAttributionSource);
verify(mService).getState();
}
@Test
public void isConnected_callsServiceStaticMethod() {
- mBinder.isConnected(mDevice, null);
-
+ mBinder.isConnected(mDevice, mAttributionSource);
verify(mService).getConnectionState(mDevice);
}
@Test
public void getClient_callsServiceStaticMethod() {
- mBinder.getClient(null);
+ mBinder.getClient(mAttributionSource);
verify(mService).getRemoteDevice();
}
@Test
- public void cleanUp_doesNotCrash() {
+ public void cleanup_doesNotCrash() {
mBinder.cleanup();
}
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/OWNERS b/android/app/tests/unit/src/com/android/bluetooth/map/OWNERS
deleted file mode 100644
index 8f87191393..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/map/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_content \ No newline at end of file
diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapapi/OWNERS b/android/app/tests/unit/src/com/android/bluetooth/mapapi/OWNERS
deleted file mode 100644
index 8f87191393..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/mapapi/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_content \ No newline at end of file
diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceBinderTest.java
index 0830f8b9f9..4e6910718f 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceBinderTest.java
@@ -24,6 +24,7 @@ import static com.android.bluetooth.TestUtils.getTestDevice;
import static org.mockito.Mockito.verify;
import android.bluetooth.BluetoothDevice;
+import android.content.AttributionSource;
import android.net.Uri;
import androidx.test.filters.MediumTest;
@@ -35,70 +36,68 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+/** Test cases for {@link MapClientServiceBinder} */
@MediumTest
@RunWith(AndroidJUnit4.class)
public class MapClientServiceBinderTest {
+
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
@Mock private MapClientService mService;
+ private final AttributionSource mAttributionSource = new AttributionSource.Builder(1).build();
private final BluetoothDevice mDevice = getTestDevice(65);
- MapClientService.Binder mBinder;
+ private MapClientServiceBinder mBinder;
@Before
public void setUp() {
- mBinder = new MapClientService.Binder(mService);
+ mBinder = new MapClientServiceBinder(mService);
}
@Test
public void connect_callsServiceMethod() {
- mBinder.connect(mDevice, null);
-
+ mBinder.connect(mDevice, mAttributionSource);
verify(mService).connect(mDevice);
}
@Test
public void disconnect_callsServiceMethod() {
- mBinder.disconnect(mDevice, null);
-
+ mBinder.disconnect(mDevice, mAttributionSource);
verify(mService).disconnect(mDevice);
}
@Test
public void getConnectedDevices_callsServiceMethod() {
- mBinder.getConnectedDevices(null);
-
+ mBinder.getConnectedDevices(mAttributionSource);
verify(mService).getConnectedDevices();
}
@Test
public void getDevicesMatchingConnectionStates_callsServiceMethod() {
int[] states = new int[] {STATE_CONNECTED};
- mBinder.getDevicesMatchingConnectionStates(states, null);
+ mBinder.getDevicesMatchingConnectionStates(states, mAttributionSource);
verify(mService).getDevicesMatchingConnectionStates(states);
}
@Test
public void getConnectionState_callsServiceMethod() {
- mBinder.getConnectionState(mDevice, null);
-
+ mBinder.getConnectionState(mDevice, mAttributionSource);
verify(mService).getConnectionState(mDevice);
}
@Test
public void setConnectionPolicy_callsServiceMethod() {
int connectionPolicy = CONNECTION_POLICY_ALLOWED;
- mBinder.setConnectionPolicy(mDevice, connectionPolicy, null);
+ mBinder.setConnectionPolicy(mDevice, connectionPolicy, mAttributionSource);
verify(mService).setConnectionPolicy(mDevice, connectionPolicy);
}
@Test
public void getConnectionPolicy_callsServiceMethod() {
- mBinder.getConnectionPolicy(mDevice, null);
-
+ mBinder.getConnectionPolicy(mDevice, mAttributionSource);
verify(mService).getConnectionPolicy(mDevice);
}
@@ -106,13 +105,13 @@ public class MapClientServiceBinderTest {
public void sendMessage_callsServiceMethod() {
Uri[] contacts = new Uri[] {};
String message = "test_message";
- mBinder.sendMessage(mDevice, contacts, message, null, null, null);
+ mBinder.sendMessage(mDevice, contacts, message, null, null, mAttributionSource);
verify(mService).sendMessage(mDevice, contacts, message, null, null);
}
@Test
- public void cleanUp_doesNotCrash() {
+ public void cleanup_doesNotCrash() {
mBinder.cleanup();
}
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/OWNERS b/android/app/tests/unit/src/com/android/bluetooth/mapclient/OWNERS
deleted file mode 100644
index 8f87191393..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_content \ No newline at end of file
diff --git a/android/app/tests/unit/src/com/android/bluetooth/mcp/McpServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/mcp/McpServiceBinderTest.java
new file mode 100644
index 0000000000..dc21e810b8
--- /dev/null
+++ b/android/app/tests/unit/src/com/android/bluetooth/mcp/McpServiceBinderTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.mcp;
+
+import static com.android.bluetooth.TestUtils.MockitoRule;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothDevice;
+import android.content.AttributionSource;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+/** Test cases for {@link McpServiceBinder} */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class McpServiceBinderTest {
+
+ @Rule public final MockitoRule mMockitoRule = new MockitoRule();
+
+ @Mock private McpService mService;
+
+ private AttributionSource mAttributionSource;
+ private McpServiceBinder mBinder;
+
+ @Before
+ public void setUp() throws Exception {
+ when(mService.isAvailable()).thenReturn(true);
+ mBinder = new McpServiceBinder(mService);
+ mAttributionSource = new AttributionSource.Builder(1).build();
+ }
+
+ @Test
+ public void setDeviceAuthorized() {
+ BluetoothDevice device = mock(BluetoothDevice.class);
+ boolean isAuthorized = true;
+
+ mBinder.setDeviceAuthorized(device, isAuthorized, mAttributionSource);
+ verify(mService).setDeviceAuthorized(device, isAuthorized);
+ }
+
+ @Test
+ public void cleanup_doesNotCrash() {
+ mBinder.cleanup();
+ }
+}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/mcp/OWNERS b/android/app/tests/unit/src/com/android/bluetooth/mcp/OWNERS
deleted file mode 100644
index a7d77894ba..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/mcp/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_leaudio
diff --git a/android/app/tests/unit/src/com/android/bluetooth/obex/OWNERS b/android/app/tests/unit/src/com/android/bluetooth/obex/OWNERS
deleted file mode 100644
index 8f87191393..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/obex/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_content \ No newline at end of file
diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferTest.java
index f6c393909c..3ab02065e3 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferTest.java
@@ -390,7 +390,6 @@ public class BluetoothOppTransferTest {
@Test
public void oppConnectionReceiver_onReceiveWithActionSdpRecord_withoutSdpRecord() {
- mSetFlagRule.enableFlags(Flags.FLAG_IDENTITY_ADDRESS_NULL_IF_NOT_KNOWN);
BluetoothDevice device =
InstrumentationRegistry.getInstrumentation()
.getTargetContext()
diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java
index 705c91d518..cadff94862 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java
@@ -44,6 +44,7 @@ import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
+import android.provider.Settings;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -432,4 +433,22 @@ public class BluetoothOppUtilityTest {
assertWithMessage("Exception should not happen. " + e).fail();
}
}
+
+ @Test
+ public void grantPermissionToNearbyComponent() {
+ Uri originalUri = Uri.parse("content://test.provider/1");
+ Settings.Secure.putString(
+ mContext.getContentResolver(),
+ "nearby_sharing_component",
+ "com.example/.BComponent");
+ Context spiedContext = spy(new ContextWrapper(mContext));
+
+ BluetoothOppUtility.grantPermissionToNearbyComponent(spiedContext, List.of(originalUri));
+
+ verify(spiedContext)
+ .grantUriPermission(
+ eq("com.example"),
+ eq(originalUri),
+ eq(Intent.FLAG_GRANT_READ_URI_PERMISSION));
+ }
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/OWNERS b/android/app/tests/unit/src/com/android/bluetooth/opp/OWNERS
deleted file mode 100644
index 8f87191393..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/opp/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_content \ No newline at end of file
diff --git a/android/app/tests/unit/src/com/android/bluetooth/pan/OWNERS b/android/app/tests/unit/src/com/android/bluetooth/pan/OWNERS
deleted file mode 100644
index 8f87191393..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/pan/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_content \ No newline at end of file
diff --git a/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceBinderTest.java
index d798666437..272ada98d7 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceBinderTest.java
@@ -25,6 +25,7 @@ import static com.android.bluetooth.TestUtils.getTestDevice;
import static org.mockito.Mockito.verify;
import android.bluetooth.BluetoothDevice;
+import android.content.AttributionSource;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -35,75 +36,73 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+/** Test cases for {@link PanServiceBinder} */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class PanServiceBinderTest {
+
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
@Mock private PanService mService;
+ private final AttributionSource mAttributionSource = new AttributionSource.Builder(1).build();
private final BluetoothDevice mDevice = getTestDevice(64);
- PanService.BluetoothPanBinder mBinder;
+ private PanServiceBinder mBinder;
@Before
public void setUp() throws Exception {
- mBinder = new PanService.BluetoothPanBinder(mService);
+ mBinder = new PanServiceBinder(mService);
}
@Test
public void connect_callsServiceMethod() {
- mBinder.connect(mDevice, null);
-
+ mBinder.connect(mDevice, mAttributionSource);
verify(mService).connect(mDevice);
}
@Test
public void disconnect_callsServiceMethod() {
- mBinder.disconnect(mDevice, null);
-
+ mBinder.disconnect(mDevice, mAttributionSource);
verify(mService).disconnect(mDevice);
}
@Test
public void getConnectedDevices_callsServiceMethod() {
- mBinder.getConnectedDevices(null);
-
+ mBinder.getConnectedDevices(mAttributionSource);
verify(mService).getConnectedDevices();
}
@Test
public void getDevicesMatchingConnectionStates_callsServiceMethod() {
int[] states = new int[] {STATE_CONNECTED};
- mBinder.getDevicesMatchingConnectionStates(states, null);
+ mBinder.getDevicesMatchingConnectionStates(states, mAttributionSource);
verify(mService).getDevicesMatchingConnectionStates(states);
}
@Test
public void getConnectionState_callsServiceMethod() {
- mBinder.getConnectionState(mDevice, null);
-
+ mBinder.getConnectionState(mDevice, mAttributionSource);
verify(mService).getConnectionState(mDevice);
}
@Test
public void setConnectionPolicy_callsServiceMethod() {
int connectionPolicy = CONNECTION_POLICY_ALLOWED;
- mBinder.setConnectionPolicy(mDevice, connectionPolicy, null);
+ mBinder.setConnectionPolicy(mDevice, connectionPolicy, mAttributionSource);
verify(mService).setConnectionPolicy(mDevice, connectionPolicy);
}
@Test
public void isTetheringOn_callsServiceMethod() {
- mBinder.isTetheringOn(null);
-
+ mBinder.isTetheringOn(mAttributionSource);
verify(mService).isTetheringOn();
}
@Test
- public void cleanUp_doesNotCrash() {
+ public void cleanup_doesNotCrash() {
mBinder.cleanup();
}
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceBinderTest.java
index 95b2bb25ef..5c713d62b5 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceBinderTest.java
@@ -25,6 +25,7 @@ import static com.android.bluetooth.TestUtils.getTestDevice;
import static org.mockito.Mockito.verify;
import android.bluetooth.BluetoothDevice;
+import android.content.AttributionSource;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
@@ -35,32 +36,35 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+/** Test cases for {@link BluetoothPbapServiceBinder} */
@MediumTest
@RunWith(AndroidJUnit4.class)
public class BluetoothPbapServiceBinderTest {
+
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
@Mock private BluetoothPbapService mService;
+ private final AttributionSource mAttributionSource = new AttributionSource.Builder(1).build();
private final BluetoothDevice mDevice = getTestDevice(60);
- BluetoothPbapService.PbapBinder mBinder;
+ private BluetoothPbapServiceBinder mBinder;
@Before
public void setUp() {
- mBinder = new BluetoothPbapService.PbapBinder(mService);
+ mBinder = new BluetoothPbapServiceBinder(mService);
}
@Test
public void disconnect_callsServiceMethod() {
- mBinder.disconnect(mDevice, null);
+ mBinder.disconnect(mDevice, mAttributionSource);
verify(mService).disconnect(mDevice);
}
@Test
public void getConnectedDevices_callsServiceMethod() {
- mBinder.getConnectedDevices(null);
+ mBinder.getConnectedDevices(mAttributionSource);
verify(mService).getConnectedDevices();
}
@@ -68,14 +72,14 @@ public class BluetoothPbapServiceBinderTest {
@Test
public void getDevicesMatchingConnectionStates_callsServiceMethod() {
int[] states = new int[] {STATE_CONNECTED};
- mBinder.getDevicesMatchingConnectionStates(states, null);
+ mBinder.getDevicesMatchingConnectionStates(states, mAttributionSource);
verify(mService).getDevicesMatchingConnectionStates(states);
}
@Test
public void getConnectionState_callsServiceMethod() {
- mBinder.getConnectionState(mDevice, null);
+ mBinder.getConnectionState(mDevice, mAttributionSource);
verify(mService).getConnectionState(mDevice);
}
@@ -83,7 +87,7 @@ public class BluetoothPbapServiceBinderTest {
@Test
public void setConnectionPolicy_callsServiceMethod() {
int connectionPolicy = CONNECTION_POLICY_ALLOWED;
- mBinder.setConnectionPolicy(mDevice, connectionPolicy, null);
+ mBinder.setConnectionPolicy(mDevice, connectionPolicy, mAttributionSource);
verify(mService).setConnectionPolicy(mDevice, connectionPolicy);
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/OWNERS b/android/app/tests/unit/src/com/android/bluetooth/pbap/OWNERS
deleted file mode 100644
index 8f87191393..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/pbap/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_content \ No newline at end of file
diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/OWNERS b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/OWNERS
deleted file mode 100644
index 8f87191393..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_content \ No newline at end of file
diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientObexTransportTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientObexTransportTest.java
index dfcc542467..b594ac70b4 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientObexTransportTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientObexTransportTest.java
@@ -183,7 +183,6 @@ public class PbapClientObexTransportTest {
public void testGetRemoteAddress_transportRfcomm_returnsDeviceIdentityAddress() {
doReturn(BluetoothSocket.TYPE_RFCOMM).when(mMockSocket).getConnectionType();
PbapClientObexTransport transport = new PbapClientObexTransport(mMockSocket);
- // See "Flags.identityAddressNullIfNotKnown():"
// Identity address won't be "known" by the stack for a test device, so it'll return null.
// assertThat(transport.getRemoteAddress()).isNull();
assertThat(transport.getRemoteAddress()).isEqualTo(mTestDevice.getAddress());
diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceBinderTest.java
index aff8f250a7..94b51136dd 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceBinderTest.java
@@ -47,29 +47,30 @@ import org.mockito.Mock;
import java.util.List;
+/** Test cases for {@link PbapClientServiceBinder} */
@MediumTest
@RunWith(AndroidJUnit4.class)
-public class PbapClientBinderTest {
+public class PbapClientServiceBinderTest {
@Rule public final MockitoRule mMockitoRule = new MockitoRule();
@Mock private PbapClientService mMockService;
private BluetoothDevice mTestDevice;
private AttributionSource mAttributionSource;
- private PbapClientBinder mPbapClientBinder;
+ private PbapClientServiceBinder mPbapClientServiceBinder;
@Before
public void setUp() throws Exception {
mTestDevice = getTestDevice(1);
mAttributionSource = new AttributionSource.Builder(1).build();
- mPbapClientBinder = new PbapClientBinder(mMockService);
+ mPbapClientServiceBinder = new PbapClientServiceBinder(mMockService);
}
@After
public void tearDown() throws Exception {
- if (mPbapClientBinder != null) {
- mPbapClientBinder.cleanup();
- mPbapClientBinder = null;
+ if (mPbapClientServiceBinder != null) {
+ mPbapClientServiceBinder.cleanup();
+ mPbapClientServiceBinder = null;
}
}
@@ -79,45 +80,46 @@ public class PbapClientBinderTest {
@Test
public void testConnect() {
- mPbapClientBinder.connect(mTestDevice, mAttributionSource);
+ mPbapClientServiceBinder.connect(mTestDevice, mAttributionSource);
verify(mMockService).connect(eq(mTestDevice));
}
@Test
public void testDisconnect() {
- mPbapClientBinder.disconnect(mTestDevice, mAttributionSource);
+ mPbapClientServiceBinder.disconnect(mTestDevice, mAttributionSource);
verify(mMockService).disconnect(eq(mTestDevice));
}
@Test
public void testGetConnectedDevices() {
- mPbapClientBinder.getConnectedDevices(mAttributionSource);
+ mPbapClientServiceBinder.getConnectedDevices(mAttributionSource);
verify(mMockService).getConnectedDevices();
}
@Test
public void testGetDevicesMatchingConnectionStates() {
int[] states = new int[] {STATE_CONNECTED};
- mPbapClientBinder.getDevicesMatchingConnectionStates(states, mAttributionSource);
+ mPbapClientServiceBinder.getDevicesMatchingConnectionStates(states, mAttributionSource);
verify(mMockService).getDevicesMatchingConnectionStates(eq(states));
}
@Test
public void testGetConnectionState() {
- mPbapClientBinder.getConnectionState(mTestDevice, mAttributionSource);
+ mPbapClientServiceBinder.getConnectionState(mTestDevice, mAttributionSource);
verify(mMockService).getConnectionState(eq(mTestDevice));
}
@Test
public void testSetConnectionPolicy() {
int connectionPolicy = CONNECTION_POLICY_ALLOWED;
- mPbapClientBinder.setConnectionPolicy(mTestDevice, connectionPolicy, mAttributionSource);
+ mPbapClientServiceBinder.setConnectionPolicy(
+ mTestDevice, connectionPolicy, mAttributionSource);
verify(mMockService).setConnectionPolicy(eq(mTestDevice), eq(connectionPolicy));
}
@Test
public void testGetConnectionPolicy() {
- mPbapClientBinder.getConnectionPolicy(mTestDevice, mAttributionSource);
+ mPbapClientServiceBinder.getConnectionPolicy(mTestDevice, mAttributionSource);
verify(mMockService).getConnectionPolicy(eq(mTestDevice));
}
@@ -127,52 +129,54 @@ public class PbapClientBinderTest {
@Test
public void testConnect_afterCleanup_returnsFalse() {
- mPbapClientBinder.cleanup();
- boolean result = mPbapClientBinder.connect(mTestDevice, mAttributionSource);
+ mPbapClientServiceBinder.cleanup();
+ boolean result = mPbapClientServiceBinder.connect(mTestDevice, mAttributionSource);
verify(mMockService, never()).connect(any(BluetoothDevice.class));
assertThat(result).isFalse();
}
@Test
public void testDisconnect_afterCleanup_returnsFalse() {
- mPbapClientBinder.cleanup();
- boolean result = mPbapClientBinder.disconnect(mTestDevice, mAttributionSource);
+ mPbapClientServiceBinder.cleanup();
+ boolean result = mPbapClientServiceBinder.disconnect(mTestDevice, mAttributionSource);
verify(mMockService, never()).disconnect(any(BluetoothDevice.class));
assertThat(result).isFalse();
}
@Test
public void testGetConnectedDevices_afterCleanup_returnsEmptyList() {
- mPbapClientBinder.cleanup();
- List<BluetoothDevice> devices = mPbapClientBinder.getConnectedDevices(mAttributionSource);
+ mPbapClientServiceBinder.cleanup();
+ List<BluetoothDevice> devices =
+ mPbapClientServiceBinder.getConnectedDevices(mAttributionSource);
verify(mMockService, never()).getConnectedDevices();
assertThat(devices).isEmpty();
}
@Test
public void testGetDevicesMatchingConnectionStates_afterCleanup_returnsEmptyList() {
- mPbapClientBinder.cleanup();
+ mPbapClientServiceBinder.cleanup();
int[] states = new int[] {STATE_CONNECTED};
List<BluetoothDevice> devices =
- mPbapClientBinder.getDevicesMatchingConnectionStates(states, mAttributionSource);
+ mPbapClientServiceBinder.getDevicesMatchingConnectionStates(
+ states, mAttributionSource);
verify(mMockService, never()).getDevicesMatchingConnectionStates(any(int[].class));
assertThat(devices).isEmpty();
}
@Test
public void testGetConnectionState_afterCleanup_returnsDisconnected() {
- mPbapClientBinder.cleanup();
- int state = mPbapClientBinder.getConnectionState(mTestDevice, mAttributionSource);
+ mPbapClientServiceBinder.cleanup();
+ int state = mPbapClientServiceBinder.getConnectionState(mTestDevice, mAttributionSource);
verify(mMockService, never()).getConnectionState(any(BluetoothDevice.class));
assertThat(state).isEqualTo(STATE_DISCONNECTED);
}
@Test
public void testSetConnectionPolicy_afterCleanup_returnsFalse() {
- mPbapClientBinder.cleanup();
+ mPbapClientServiceBinder.cleanup();
int connectionPolicy = CONNECTION_POLICY_ALLOWED;
boolean result =
- mPbapClientBinder.setConnectionPolicy(
+ mPbapClientServiceBinder.setConnectionPolicy(
mTestDevice, connectionPolicy, mAttributionSource);
verify(mMockService, never()).setConnectionPolicy(any(BluetoothDevice.class), anyInt());
assertThat(result).isFalse();
@@ -180,8 +184,8 @@ public class PbapClientBinderTest {
@Test
public void testGetConnectionPolicy_afterCleanup_returnsUnknown() {
- mPbapClientBinder.cleanup();
- int result = mPbapClientBinder.getConnectionPolicy(mTestDevice, mAttributionSource);
+ mPbapClientServiceBinder.cleanup();
+ int result = mPbapClientServiceBinder.getConnectionPolicy(mTestDevice, mAttributionSource);
verify(mMockService, never()).getConnectionPolicy(any(BluetoothDevice.class));
assertThat(result).isEqualTo(CONNECTION_POLICY_UNKNOWN);
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/sap/OWNERS b/android/app/tests/unit/src/com/android/bluetooth/sap/OWNERS
deleted file mode 100644
index 8f87191393..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/sap/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_content \ No newline at end of file
diff --git a/android/app/tests/unit/src/com/android/bluetooth/sap/SapServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/sap/SapServiceBinderTest.java
new file mode 100644
index 0000000000..10d1a092e0
--- /dev/null
+++ b/android/app/tests/unit/src/com/android/bluetooth/sap/SapServiceBinderTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.sap;
+
+import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+
+import static com.android.bluetooth.TestUtils.MockitoRule;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothDevice;
+import android.content.AttributionSource;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+/** Test cases for {@link SapServiceBinder} */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SapServiceBinderTest {
+
+ @Rule public final MockitoRule mMockitoRule = new MockitoRule();
+
+ @Mock private SapService mService;
+
+ private AttributionSource mAttributionSource;
+ private SapServiceBinder mBinder;
+
+ @Before
+ public void setUp() throws Exception {
+ when(mService.isAvailable()).thenReturn(true);
+ mBinder = new SapServiceBinder(mService);
+ mAttributionSource = new AttributionSource.Builder(1).build();
+ }
+
+ @Test
+ public void getState() {
+ mBinder.getState(mAttributionSource);
+ verify(mService).getState();
+ }
+
+ @Test
+ public void getClient() {
+ mBinder.getClient(mAttributionSource);
+ // times(2) due to the Log
+ verify(mService, times(2)).getRemoteDevice();
+ }
+
+ @Test
+ public void isConnected() {
+ BluetoothDevice device = mock(BluetoothDevice.class);
+
+ mBinder.isConnected(device, mAttributionSource);
+ verify(mService).getConnectionState(device);
+ }
+
+ @Test
+ public void disconnect() {
+ BluetoothDevice device = mock(BluetoothDevice.class);
+
+ mBinder.disconnect(device, mAttributionSource);
+ verify(mService).disconnect(device);
+ }
+
+ @Test
+ public void getConnectedDevices() {
+ mBinder.getConnectedDevices(mAttributionSource);
+ verify(mService).getConnectedDevices();
+ }
+
+ @Test
+ public void getDevicesMatchingConnectionStates() {
+ int[] states = new int[] {STATE_CONNECTED, STATE_DISCONNECTED};
+
+ mBinder.getDevicesMatchingConnectionStates(states, mAttributionSource);
+ verify(mService).getDevicesMatchingConnectionStates(states);
+ }
+
+ @Test
+ public void getConnectionState() {
+ BluetoothDevice device = mock(BluetoothDevice.class);
+
+ mBinder.getConnectionState(device, mAttributionSource);
+ verify(mService).getConnectionState(device);
+ }
+
+ @Test
+ public void setConnectionPolicy() {
+ BluetoothDevice device = mock(BluetoothDevice.class);
+ int connectionPolicy = 1;
+
+ mBinder.setConnectionPolicy(device, connectionPolicy, mAttributionSource);
+ verify(mService).setConnectionPolicy(device, connectionPolicy);
+ }
+
+ @Test
+ public void getConnectionPolicy() {
+ BluetoothDevice device = mock(BluetoothDevice.class);
+
+ mBinder.getConnectionPolicy(device, mAttributionSource);
+ verify(mService).getConnectionPolicy(device);
+ }
+
+ @Test
+ public void cleanup_doesNotCrash() {
+ mBinder.cleanup();
+ }
+}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsServiceBinderTest.java
new file mode 100644
index 0000000000..7758d101b1
--- /dev/null
+++ b/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsServiceBinderTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.tbs;
+
+import static com.android.bluetooth.TestUtils.MockitoRule;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothLeCall;
+import android.bluetooth.IBluetoothLeCallControlCallback;
+import android.content.AttributionSource;
+import android.os.ParcelUuid;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+/** Test cases for {@link TbsServiceBinder} */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TbsServiceBinderTest {
+
+ @Rule public final MockitoRule mMockitoRule = new MockitoRule();
+
+ @Mock private TbsService mService;
+
+ private AttributionSource mAttributionSource;
+ private TbsServiceBinder mBinder;
+
+ @Before
+ public void setUp() throws Exception {
+ when(mService.isAvailable()).thenReturn(true);
+ mBinder = new TbsServiceBinder(mService);
+ mAttributionSource = new AttributionSource.Builder(1).build();
+ }
+
+ @Test
+ public void registerBearer() {
+ String token = "token";
+ IBluetoothLeCallControlCallback callback = mock(IBluetoothLeCallControlCallback.class);
+ String uci = "uci";
+ List<String> uriSchemes = new ArrayList<>();
+ int capabilities = 1;
+ String providerName = "providerName";
+ int technology = 2;
+
+ mBinder.registerBearer(
+ token,
+ callback,
+ uci,
+ uriSchemes,
+ capabilities,
+ providerName,
+ technology,
+ mAttributionSource);
+ verify(mService)
+ .registerBearer(
+ token, callback, uci, uriSchemes, capabilities, providerName, technology);
+ }
+
+ @Test
+ public void unregisterBearer() {
+ String token = "token";
+
+ mBinder.unregisterBearer(token, mAttributionSource);
+ verify(mService).unregisterBearer(token);
+ }
+
+ @Test
+ public void requestResult() {
+ int ccid = 1;
+ int requestId = 2;
+ int result = 3;
+
+ mBinder.requestResult(ccid, requestId, result, mAttributionSource);
+ verify(mService).requestResult(ccid, requestId, result);
+ }
+
+ @Test
+ public void callAdded() {
+ int ccid = 1;
+ BluetoothLeCall call = mock(BluetoothLeCall.class);
+
+ mBinder.callAdded(ccid, call, mAttributionSource);
+ verify(mService).callAdded(ccid, call);
+ }
+
+ @Test
+ public void callRemoved() {
+ int ccid = 1;
+ UUID callId = UUID.randomUUID();
+ int reason = 2;
+
+ mBinder.callRemoved(ccid, new ParcelUuid(callId), reason, mAttributionSource);
+ verify(mService).callRemoved(ccid, callId, reason);
+ }
+
+ @Test
+ public void callStateChanged() {
+ int ccid = 1;
+ UUID callId = UUID.randomUUID();
+ int state = 2;
+
+ mBinder.callStateChanged(ccid, new ParcelUuid(callId), state, mAttributionSource);
+ verify(mService).callStateChanged(ccid, callId, state);
+ }
+
+ @Test
+ public void currentCallsList() {
+ int ccid = 1;
+ List<BluetoothLeCall> calls = new ArrayList<>();
+
+ mBinder.currentCallsList(ccid, calls, mAttributionSource);
+ verify(mService).currentCallsList(ccid, calls);
+ }
+
+ @Test
+ public void cleanup_doesNotCrash() {
+ mBinder.cleanup();
+ }
+}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/OWNERS b/android/app/tests/unit/src/com/android/bluetooth/vc/OWNERS
deleted file mode 100644
index a7d77894ba..0000000000
--- a/android/app/tests/unit/src/com/android/bluetooth/vc/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_leaudio
diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceBinderTest.java
new file mode 100644
index 0000000000..32296381c8
--- /dev/null
+++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceBinderTest.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2025 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.bluetooth.vc;
+
+import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
+
+import static com.android.bluetooth.TestUtils.MockitoRule;
+import static com.android.bluetooth.TestUtils.getTestDevice;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.IAudioInputCallback;
+import android.content.AttributionSource;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+/** Test cases for {@link VolumeControlServiceBinder} */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class VolumeControlServiceBinderTest {
+
+ @Rule public final MockitoRule mMockitoRule = new MockitoRule();
+
+ @Mock private VolumeControlService mService;
+
+ private final BluetoothDevice mDevice = getTestDevice(25);
+
+ private AttributionSource mAttributionSource;
+ private VolumeControlServiceBinder mBinder;
+
+ @Before
+ public void setUp() throws Exception {
+ when(mService.isAvailable()).thenReturn(true);
+ mBinder = new VolumeControlServiceBinder(mService);
+ mAttributionSource = new AttributionSource.Builder(1).build();
+ }
+
+ @Test
+ public void getConnectedDevices() {
+ mBinder.getConnectedDevices(mAttributionSource);
+ verify(mService).getConnectedDevices();
+ }
+
+ @Test
+ public void getDevicesMatchingConnectionStates() {
+ int[] states = new int[] {STATE_CONNECTED};
+
+ mBinder.getDevicesMatchingConnectionStates(states, mAttributionSource);
+ verify(mService).getDevicesMatchingConnectionStates(states);
+ }
+
+ @Test
+ public void getConnectionState() {
+ mBinder.getConnectionState(mDevice, mAttributionSource);
+ verify(mService).getConnectionState(mDevice);
+ }
+
+ @Test
+ public void setConnectionPolicy() {
+ int connectionPolicy = 1;
+
+ mBinder.setConnectionPolicy(mDevice, connectionPolicy, mAttributionSource);
+ verify(mService).setConnectionPolicy(mDevice, connectionPolicy);
+ }
+
+ @Test
+ public void getConnectionPolicy() {
+ mBinder.getConnectionPolicy(mDevice, mAttributionSource);
+ verify(mService).getConnectionPolicy(mDevice);
+ }
+
+ @Test
+ public void isVolumeOffsetAvailable() {
+ mBinder.isVolumeOffsetAvailable(mDevice, mAttributionSource);
+ verify(mService).isVolumeOffsetAvailable(mDevice);
+ }
+
+ @Test
+ public void getNumberOfVolumeOffsetInstances() {
+ mBinder.getNumberOfVolumeOffsetInstances(mDevice, mAttributionSource);
+ verify(mService).getNumberOfVolumeOffsetInstances(mDevice);
+ }
+
+ @Test
+ public void setVolumeOffset() {
+ int instanceId = 1;
+ int volumeOffset = 2;
+
+ mBinder.setVolumeOffset(mDevice, instanceId, volumeOffset, mAttributionSource);
+ verify(mService).setVolumeOffset(mDevice, instanceId, volumeOffset);
+ }
+
+ @Test
+ public void setDeviceVolume() {
+ int volume = 1;
+ boolean isGroupOp = true;
+
+ mBinder.setDeviceVolume(mDevice, volume, isGroupOp, mAttributionSource);
+ verify(mService).setDeviceVolume(mDevice, volume, isGroupOp);
+ }
+
+ @Test
+ public void setGroupVolume() {
+ int groupId = 1;
+ int volume = 2;
+
+ mBinder.setGroupVolume(groupId, volume, mAttributionSource);
+ verify(mService).setGroupVolume(groupId, volume);
+ }
+
+ @Test
+ public void getGroupVolume() {
+ int groupId = 1;
+
+ mBinder.getGroupVolume(groupId, mAttributionSource);
+ verify(mService).getGroupVolume(groupId);
+ }
+
+ @Test
+ public void setGroupActive() {
+ int groupId = 1;
+ boolean active = true;
+
+ mBinder.setGroupActive(groupId, active, mAttributionSource);
+ verify(mService).setGroupActive(groupId, active);
+ }
+
+ @Test
+ public void mute() {
+ mBinder.mute(mDevice, mAttributionSource);
+ verify(mService).mute(mDevice);
+ }
+
+ @Test
+ public void muteGroup() {
+ int groupId = 1;
+ mBinder.muteGroup(groupId, mAttributionSource);
+ verify(mService).muteGroup(groupId);
+ }
+
+ @Test
+ public void unmute() {
+ mBinder.unmute(mDevice, mAttributionSource);
+ verify(mService).unmute(mDevice);
+ }
+
+ @Test
+ public void unmuteGroup() {
+ int groupId = 1;
+
+ mBinder.unmuteGroup(groupId, mAttributionSource);
+ verify(mService).unmuteGroup(groupId);
+ }
+
+ @Test
+ public void getNumberOfAudioInputControlServices() {
+ mBinder.getNumberOfAudioInputControlServices(mAttributionSource, mDevice);
+ }
+
+ @Test
+ public void registerAudioInputControlCallback() {
+ int instanceId = 1;
+ IAudioInputCallback callback = mock(IAudioInputCallback.class);
+
+ mBinder.registerAudioInputControlCallback(
+ mAttributionSource, mDevice, instanceId, callback);
+ }
+
+ @Test
+ public void unregisterAudioInputControlCallback() {
+ int instanceId = 1;
+ IAudioInputCallback callback = mock(IAudioInputCallback.class);
+
+ mBinder.unregisterAudioInputControlCallback(
+ mAttributionSource, mDevice, instanceId, callback);
+ }
+
+ @Test
+ public void getAudioInputGainSettingUnit() {
+ int instanceId = 1;
+ mBinder.getAudioInputGainSettingUnit(mAttributionSource, mDevice, instanceId);
+ }
+
+ @Test
+ public void getAudioInputGainSettingMin() {
+ int instanceId = 1;
+ mBinder.getAudioInputGainSettingMin(mAttributionSource, mDevice, instanceId);
+ }
+
+ @Test
+ public void getAudioInputGainSettingMax() {
+ int instanceId = 1;
+ mBinder.getAudioInputGainSettingMax(mAttributionSource, mDevice, instanceId);
+ }
+
+ @Test
+ public void getAudioInputDescription() {
+ int instanceId = 1;
+ mBinder.getAudioInputDescription(mAttributionSource, mDevice, instanceId);
+ }
+
+ @Test
+ public void isAudioInputDescriptionWritable() {
+ int instanceId = 1;
+ mBinder.isAudioInputDescriptionWritable(mAttributionSource, mDevice, instanceId);
+ }
+
+ @Test
+ public void setAudioInputDescription() {
+ int instanceId = 1;
+ String description = "test";
+ mBinder.setAudioInputDescription(mAttributionSource, mDevice, instanceId, description);
+ }
+
+ @Test
+ public void getAudioInputStatus() {
+ int instanceId = 1;
+ mBinder.getAudioInputStatus(mAttributionSource, mDevice, instanceId);
+ }
+
+ @Test
+ public void getAudioInputType() {
+ int instanceId = 1;
+ mBinder.getAudioInputType(mAttributionSource, mDevice, instanceId);
+ }
+
+ @Test
+ public void getAudioInputGainSetting() {
+ int instanceId = 1;
+ mBinder.getAudioInputGainSetting(mAttributionSource, mDevice, instanceId);
+ }
+
+ @Test
+ public void setAudioInputGainSetting() {
+ int instanceId = 1;
+ int gainSetting = 2;
+ mBinder.setAudioInputGainSetting(mAttributionSource, mDevice, instanceId, gainSetting);
+ }
+
+ @Test
+ public void getAudioInputGainMode() {
+ int instanceId = 1;
+ mBinder.getAudioInputGainMode(mAttributionSource, mDevice, instanceId);
+ }
+
+ @Test
+ public void setAudioInputGainMode() {
+ int instanceId = 1;
+ int gainMode = 2;
+ mBinder.setAudioInputGainMode(mAttributionSource, mDevice, instanceId, gainMode);
+ }
+
+ @Test
+ public void getAudioInputMute() {
+ int instanceId = 1;
+ mBinder.getAudioInputMute(mAttributionSource, mDevice, instanceId);
+ }
+
+ @Test
+ public void setAudioInputMute() {
+ int instanceId = 1;
+ int mute = 2;
+ mBinder.setAudioInputMute(mAttributionSource, mDevice, instanceId, mute);
+ }
+
+ @Test
+ public void cleanup_doesNotCrash() {
+ mBinder.cleanup();
+ }
+}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java
index 35d8ee3ce1..9412ebfe40 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java
@@ -128,7 +128,7 @@ public class VolumeControlServiceTest {
private AttributionSource mAttributionSource;
private VolumeControlService mService;
- private VolumeControlService.BluetoothVolumeControlBinder mBinder;
+ private VolumeControlServiceBinder mBinder;
private InOrder mInOrder;
private TestLooper mLooper;
@@ -174,7 +174,7 @@ public class VolumeControlServiceTest {
mService.setAvailable(true);
mService.mFactory = mServiceFactory;
- mBinder = (VolumeControlService.BluetoothVolumeControlBinder) mService.initBinder();
+ mBinder = (VolumeControlServiceBinder) mService.initBinder();
}
@After
diff --git a/android/leaudio/OWNERS b/android/leaudio/OWNERS
deleted file mode 100644
index a7d77894ba..0000000000
--- a/android/leaudio/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_leaudio
diff --git a/android/pandora/OWNERS b/android/pandora/OWNERS
deleted file mode 100644
index c199a82a60..0000000000
--- a/android/pandora/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 1099313
-girardier@google.com
diff --git a/android/pandora/test/main.py b/android/pandora/test/main.py
index d5c5da0bad..7e49321932 100644
--- a/android/pandora/test/main.py
+++ b/android/pandora/test/main.py
@@ -25,6 +25,7 @@ import avatar.cases.security_test
import gatt_test
import hap_test
import hfpclient_test
+import rfcomm_test
import sdp_test
from pairing import _test_class_list as _pairing_test_class_list
@@ -81,6 +82,7 @@ _TEST_CLASSES_LIST = [
hap_test.HapTest,
asha_test.AshaTest,
hfpclient_test.HfpClientTest,
+ rfcomm_test.RfcommTest,
] + _pairing_test_class_list
diff --git a/android/pandora/test/pairing/OWNERS b/android/pandora/test/pairing/OWNERS
deleted file mode 100644
index b430ae987d..0000000000
--- a/android/pandora/test/pairing/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 27441
-rwt@google.com
diff --git a/android/pandora/test/rfcomm_test.py b/android/pandora/test/rfcomm_test.py
new file mode 100644
index 0000000000..4409b02e25
--- /dev/null
+++ b/android/pandora/test/rfcomm_test.py
@@ -0,0 +1,110 @@
+# Copyright 2025 Google LLC
+#
+# 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
+#
+# https://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.
+
+import asyncio
+import avatar
+import grpc
+import logging
+
+from avatar import PandoraDevices
+from avatar.aio import asynchronous
+from avatar.pandora_client import BumblePandoraClient, PandoraClient
+from bumble.rfcomm import Server
+from bumble_experimental.rfcomm import RFCOMMService
+from mobly import base_test, test_runner
+from mobly.asserts import assert_equal # type: ignore
+from mobly.asserts import assert_in # type: ignore
+from mobly.asserts import assert_is_not_none # type: ignore
+from mobly.asserts import fail # type: ignore
+from pandora_experimental.rfcomm_grpc_aio import RFCOMM
+from pandora_experimental.rfcomm_pb2 import (
+ AcceptConnectionRequest,
+ RxRequest,
+ StartServerRequest,
+ StopServerRequest,
+ TxRequest,
+)
+from typing import Optional, Tuple
+
+SERIAL_PORT_UUID = "00001101-0000-1000-8000-00805F9B34FB"
+TEST_SERVER_NAME = "RFCOMM-Server"
+
+
+class RfcommTest(base_test.BaseTestClass):
+ devices: Optional[PandoraDevices] = None
+ dut: PandoraClient
+ ref: BumblePandoraClient
+
+ def setup_class(self) -> None:
+ self.devices = PandoraDevices(self)
+ self.dut, ref, *_ = self.devices
+ assert isinstance(ref, BumblePandoraClient)
+ self.ref = ref
+ # Enable BR/EDR mode and SSP for Bumble devices.
+ self.ref.config.setdefault('classic_enabled', True)
+ self.ref.config.setdefault('classic_ssp_enabled', True)
+ self.ref.config.setdefault(
+ 'server',
+ {
+ 'io_capability': 'no_output_no_input',
+ },
+ )
+
+ def teardown_class(self) -> None:
+ if self.devices:
+ self.devices.stop_all()
+
+ @avatar.asynchronous
+ async def setup_test(self) -> None:
+ await asyncio.gather(self.dut.reset(), self.ref.reset())
+
+ ref_server = Server(self.ref.device)
+ self.ref.rfcomm = RFCOMMService(self.ref.device, ref_server)
+ self.dut.rfcomm = RFCOMM(channel=self.dut.aio.channel)
+
+ @avatar.asynchronous
+ async def test_client_connect_and_exchange_data(self) -> None:
+ # dut is client, ref is server
+ context = grpc.ServicerContext
+ server = await self.ref.rfcomm.StartServer(StartServerRequest(name=TEST_SERVER_NAME, uuid=SERIAL_PORT_UUID),
+ context=context)
+ # Convert StartServerResponse to its server
+ server = server.server
+ rfc_dut_ref, rfc_ref_dut = await asyncio.gather(
+ self.dut.rfcomm.ConnectToServer(address=self.ref.address, uuid=SERIAL_PORT_UUID),
+ self.ref.rfcomm.AcceptConnection(request=AcceptConnectionRequest(server=server), context=context))
+ # Convert Responses to their corresponding RfcommConnection
+ rfc_dut_ref = rfc_dut_ref.connection
+ rfc_ref_dut = rfc_ref_dut.connection
+
+ # Transmit data
+ tx_data = b'Data from dut to ref'
+ await self.dut.rfcomm.Send(data=tx_data, connection=rfc_dut_ref)
+ ref_receive = await self.ref.rfcomm.Receive(request=RxRequest(connection=rfc_ref_dut), context=context)
+ assert_equal(ref_receive.data, tx_data)
+
+ # Receive data
+ rx_data = b'Data from ref to dut'
+ await self.ref.rfcomm.Send(request=TxRequest(connection=rfc_ref_dut, data=rx_data), context=context)
+ dut_receive = await self.dut.rfcomm.Receive(connection=rfc_dut_ref)
+ assert_equal(dut_receive.data.rstrip(b'\x00'), rx_data)
+
+ # Disconnect (from dut)
+ await self.dut.rfcomm.Disconnect(connection=rfc_dut_ref)
+ await self.ref.rfcomm.StopServer(request=StopServerRequest(server=server), context=context)
+
+
+if __name__ == '__main__':
+ logging.basicConfig(level=logging.DEBUG)
+ test_runner.main() # type: ignore
diff --git a/apex/Android.bp b/apex/Android.bp
index c2aabcf0b8..bf75163768 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -84,7 +84,6 @@ apex {
],
key: "com.android.bt.key",
certificate: ":com.android.bt.certificate",
- updatable: true,
compressible: false,
visibility: ["//packages/modules/common/build"],
}
diff --git a/apex/OWNERS b/apex/OWNERS
deleted file mode 100644
index cc88477d0e..0000000000
--- a/apex/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Reviewers for /apex
-
-wescande@google.com
-
diff --git a/apex/hiddenapi/OWNERS b/apex/hiddenapi/OWNERS
deleted file mode 100644
index ac8a2b627c..0000000000
--- a/apex/hiddenapi/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# soong-team@ as the hiddenapi files are tightly coupled with Soong
-file:platform/build/soong:/OWNERS
-
-# compat-team@ for changes to hiddenapi files
-file:tools/platform-compat:/OWNERS
diff --git a/apex/permissions/OWNERS b/apex/permissions/OWNERS
deleted file mode 100644
index 8b8ec67028..0000000000
--- a/apex/permissions/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-per-file *.xml,OWNERS = file:platform/frameworks/base:/data/etc/OWNERS
diff --git a/build.py b/build.py
index 1f2a925351..de97ce855e 100755
--- a/build.py
+++ b/build.py
@@ -86,7 +86,6 @@ HOST_TESTS = [
# 'bluetooth_test_common',
# 'bluetoothtbd_test',
# 'net_test_avrcp',
- # 'net_test_btcore',
# 'net_test_types',
# 'net_test_btm_iso',
# 'net_test_btpackets',
diff --git a/common/OWNERS b/common/OWNERS
deleted file mode 100644
index 5b3f4bad26..0000000000
--- a/common/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-wescande@google.com
diff --git a/flags/OWNERS b/flags/OWNERS
deleted file mode 100644
index b4f2f7376b..0000000000
--- a/flags/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 1387432
-girardier@google.com
-wescande@google.com
diff --git a/flags/a2dp.aconfig b/flags/a2dp.aconfig
index e7b9aa21b0..1fd8bbd085 100644
--- a/flags/a2dp.aconfig
+++ b/flags/a2dp.aconfig
@@ -115,3 +115,13 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "avdtp_prevent_double_suspend"
+ namespace: "bluetooth"
+ description: "Add state to prevent sending multiple AVDTP Suspend command in a row"
+ bug: "402241316"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/flags/bta_dm.aconfig b/flags/bta_dm.aconfig
index 19e8418785..be510f63cd 100644
--- a/flags/bta_dm.aconfig
+++ b/flags/bta_dm.aconfig
@@ -9,16 +9,6 @@ flag {
}
flag {
- name: "cancel_open_discovery_client"
- namespace: "bluetooth"
- description: "Cancel connection from discovery client correctly"
- bug: "356168480"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "extend_and_randomize_role_switch_delay"
namespace: "bluetooth"
description: "Fix the possible conflicts between role switch and authentication"
diff --git a/flags/connectivity.aconfig b/flags/connectivity.aconfig
index 482c7e68e8..738c294078 100644
--- a/flags/connectivity.aconfig
+++ b/flags/connectivity.aconfig
@@ -2,30 +2,6 @@ package: "com.android.bluetooth.flags"
container: "com.android.bt"
flag {
- name: "api_get_connection_state_using_identity_address"
- namespace: "bluetooth"
- description: "Use identity address to check current connection state"
- bug: "319471537"
-}
-
-flag {
- name: "use_le_shim_connection_map_guard"
- namespace: "bluetooth"
- description: "Guard the le shim connection map with a mutex"
- bug: "302054609"
-}
-
-flag {
- name: "improve_create_connection_for_already_connecting_device"
- namespace: "bluetooth"
- description: "Make sure to not stop controller with create connection cancel when not needed"
- bug: "356593752"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "allow_gatt_connect_from_the_apps_without_making_leaudio_device_active"
namespace: "bluetooth"
description: "Allows for GATT connection without making LeAudio device active after connection"
diff --git a/flags/framework.aconfig b/flags/framework.aconfig
index dc48541118..0151b46c70 100644
--- a/flags/framework.aconfig
+++ b/flags/framework.aconfig
@@ -10,16 +10,6 @@ flag {
}
flag {
- name: "identity_address_null_if_not_known"
- namespace: "bluetooth"
- description: "Return null for identity address if identity address is not known"
- bug: "317120534"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "support_bluetooth_quality_report_v6"
is_exported: true
namespace: "bluetooth"
diff --git a/flags/gap.aconfig b/flags/gap.aconfig
index d12e294ec7..9dcdcd4b2b 100644
--- a/flags/gap.aconfig
+++ b/flags/gap.aconfig
@@ -30,13 +30,6 @@ flag {
}
flag {
- name: "ble_scan_adv_metrics_redesign"
- namespace: "bluetooth"
- description: "Reimplement BLE scan and advertisement metrics logging."
- bug: "328303508"
-}
-
-flag {
name: "msft_addr_tracking_quirk"
namespace: "bluetooth"
description: "Scanning with MSFT paddress tracking for Realtek BT controllers"
@@ -57,33 +50,6 @@ flag {
}
flag {
- name: "gatt_client_dynamic_allocation"
- namespace: "bluetooth"
- description: "Allocate GATT clients in heap to unlimit the number of clients"
- bug: "348559823"
-}
-
-flag {
- name: "gatt_fix_multiple_direct_connect"
- namespace: "bluetooth"
- description: "Do not remove device when multiple clients attempt to connect"
- bug: "349232327"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
- name: "pan_use_identity_address"
- namespace: "bluetooth"
- description: "Use identity address when communicate with native interface"
- bug: "351961492"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "android_os_identifier"
namespace: "bluetooth"
description: "Add a custom service to provide Android OS identifier"
@@ -104,33 +70,6 @@ flag {
}
flag {
- name: "non_wake_alarm_for_rpa_rotation"
- namespace: "bluetooth"
- description: "Use non-wake alarm for LE RPA rotation. go/non-wake-alarm-for-rpa-rotation"
- bug: "360743527"
-}
-
-flag {
- name: "gatt_disconnect_fix"
- namespace: "bluetooth"
- description: "Fix GATT disconnect handling"
- bug: "361538527"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
- name: "gatt_server_requests_fix"
- namespace: "bluetooth"
- description: "Fix GATT server handling"
- bug: "361331170"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "le_scan_msft_support"
namespace: "bluetooth"
description: "Support MSFT HCI extension for LE Scanning. go/bt-msft-aosp-dd"
@@ -206,16 +145,6 @@ flag {
}
flag {
- name: "drop_acl_fragment_on_disconnect"
- namespace: "bluetooth"
- description: "Drop pending ACL packet fragments for disconnected connection"
- bug: "376379859"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "configure_scan_on_resume"
namespace: "bluetooth"
description: "Configure scan paramters when start scanning from onResume"
@@ -324,3 +253,13 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "le_disconnect_notification_handling"
+ namespace: "bluetooth"
+ description: "Fix LE link disconnection notification to stack's upper layers"
+ bug: "403433488"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/flags/hci.aconfig b/flags/hci.aconfig
index cdd5ca3ab6..6f6b1e70df 100644
--- a/flags/hci.aconfig
+++ b/flags/hci.aconfig
@@ -2,13 +2,6 @@ package: "com.android.bluetooth.flags"
container: "com.android.bt"
flag {
- name: "encryption_change_v2"
- namespace: "bluetooth"
- description: "Enable encryption change V2 event"
- bug: "366018699"
-}
-
-flag {
name: "dont_send_hci_disconnect_repeatedly"
namespace: "bluetooth"
description: "Prevent BT from sending repeated HCI disconnect command"
diff --git a/flags/hfp.aconfig b/flags/hfp.aconfig
index c1611242aa..9e3bd50b5d 100644
--- a/flags/hfp.aconfig
+++ b/flags/hfp.aconfig
@@ -132,3 +132,13 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "hfp_volume_control_property"
+ namespace: "bluetooth"
+ description: "Check system property before hands-free volume UI request."
+ bug: "404152232"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/flags/hid.aconfig b/flags/hid.aconfig
index d40e55821f..350367818b 100644
--- a/flags/hid.aconfig
+++ b/flags/hid.aconfig
@@ -20,16 +20,6 @@ flag {
}
flag {
- name: "serialize_hogp_and_dis"
- namespace: "bluetooth"
- description: "start HOGP service discovery only after DIS discovery is finished"
- bug: "367910199"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "dont_send_hid_set_idle"
namespace: "bluetooth"
description: "Don't send the SET IDLE HID message"
@@ -40,16 +30,6 @@ flag {
}
flag {
- name: "forward_get_set_report_failure_to_uhid"
- namespace: "bluetooth"
- description: "Forward GET/SET REPORT reply to UHID even when the request fails"
- bug: "369748430"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "remove_pending_hid_connection"
namespace: "bluetooth"
description: "Remove the pending BTA HH connection instance when the device is removed"
@@ -118,3 +98,23 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "hh_state_update_race_fix"
+ namespace: "bluetooth"
+ description: "Fix stuck in connecting state due to race when updating state"
+ bug: "403420458"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "simpler_hid_connection_policy"
+ namespace: "bluetooth"
+ description: "Simplify native HID host connection policy enforcement"
+ bug: "404590499"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/flags/l2cap.aconfig b/flags/l2cap.aconfig
index fec2edd6d5..f82b596674 100644
--- a/flags/l2cap.aconfig
+++ b/flags/l2cap.aconfig
@@ -9,16 +9,6 @@ flag {
}
flag {
- name: "l2cap_le_do_not_adjust_min_interval"
- namespace: "bluetooth"
- description: "Do not adjust min_interval in connection update request"
- bug: "346960036"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "l2cap_fcs_option_fix"
namespace: "bluetooth"
description: "Use fcs_option for non BASIC mode "
diff --git a/flags/leaudio.aconfig b/flags/leaudio.aconfig
index 9d2c86afa3..a2f77b5658 100644
--- a/flags/leaudio.aconfig
+++ b/flags/leaudio.aconfig
@@ -344,3 +344,13 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "leaudio_use_aggressive_params"
+ namespace: "bluetooth"
+ description: "use aggressive parameters for LE Audio device"
+ bug: "400607635"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/flags/opp.aconfig b/flags/opp.aconfig
index 73604961fe..cdba75b756 100644
--- a/flags/opp.aconfig
+++ b/flags/opp.aconfig
@@ -2,16 +2,6 @@ package: "com.android.bluetooth.flags"
container: "com.android.bt"
flag {
- name: "opp_ignore_content_observer_after_service_stop"
- namespace: "bluetooth"
- description: "When OppService.stop() is called, previously posted ContentObserver.onChange() should not run"
- bug: "346467641"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "opp_set_insets_for_edge_to_edge"
namespace: "bluetooth"
description: "Set proper insets in BluetoothOppTransferHistory to adapt to edge-to-edge."
@@ -41,3 +31,20 @@ flag {
}
}
+flag {
+ name: "opp_device_picker_extra_intent_apis"
+ is_exported: true
+ namespace: "bluetooth"
+ description: "New API to get the original intent in Bluetooth Device Picker"
+ bug: "395796600"
+}
+
+flag {
+ name: "send_opp_device_picker_extra_intent"
+ namespace: "bluetooth"
+ description: "Send the original intent when opening Bluetooth device picker"
+ bug: "397852103"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/flags/pairing.aconfig b/flags/pairing.aconfig
index bc57bafe9e..faae7d2618 100644
--- a/flags/pairing.aconfig
+++ b/flags/pairing.aconfig
@@ -102,16 +102,6 @@ flag {
}
flag {
- name: "smp_state_machine_stuck_after_disconnection_fix"
- namespace: "bluetooth"
- description: "Fix state machine stuck after pairing device disconnection"
- bug: "376306092"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "prevent_service_connections_on_remove_bond"
namespace: "bluetooth"
description: "Disable service connections on remove bond"
@@ -260,3 +250,33 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "le_peripheral_enc_failure"
+ namespace: "bluetooth"
+ description: "Don't remove bond on LE encryption failure in peripheral role with bonded device, instead just disconnect the link"
+ bug: "403313352"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "immediate_encryption_after_pairing"
+ namespace: "bluetooth"
+ description: "Encrypt BR/EDR link immediately after pairing"
+ bug: "402510244"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "unrelated_device_smp_cancellation"
+ namespace: "bluetooth"
+ description: "Don't cancel SMP pairing if encryption fails for unrelated device"
+ bug: "404658828"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/flags/security.aconfig b/flags/security.aconfig
index c83dc02b24..8d5a8c1f31 100644
--- a/flags/security.aconfig
+++ b/flags/security.aconfig
@@ -2,13 +2,6 @@ package: "com.android.bluetooth.flags"
container: "com.android.bt"
flag {
- name: "key_missing_classic_device"
- namespace: "bluetooth"
- description: "Key missing broadcast for Classic devices"
- bug: "333634398"
-}
-
-flag {
name: "key_missing_ble_peripheral"
namespace: "bluetooth"
description: "Key missing broadcast for LE devices in peripheral role"
@@ -66,16 +59,6 @@ flag {
}
flag {
- name: "sec_disconnect_on_le_key_missing"
- namespace: "bluetooth"
- description: "Disconnect LE link when keys are missing during encryption"
- bug: "376680866"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "guard_bonded_device_properties"
namespace: "bluetooth"
description: "Don't update device properties for bonded devices from the device discovery results"
diff --git a/flags/sockets.aconfig b/flags/sockets.aconfig
index 2eb23b1fcb..6b31e06705 100644
--- a/flags/sockets.aconfig
+++ b/flags/sockets.aconfig
@@ -92,3 +92,13 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "fix_lecoc_socket_available"
+ namespace: "bluetooth"
+ description: "Fix Bluetooth Socket available API for LECOC socket"
+ bug: "402536099"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/flags/system_service.aconfig b/flags/system_service.aconfig
index ea40eb33de..c1cf4f6bd8 100644
--- a/flags/system_service.aconfig
+++ b/flags/system_service.aconfig
@@ -2,6 +2,16 @@ package: "com.android.bluetooth.flags"
container: "com.android.bt"
flag {
+ name: "enable_ble_while_disabling_airplane"
+ namespace: "bluetooth"
+ description: "Fix a race between enabling and handling airplane event"
+ bug: "402563502"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "kill_instead_of_exit"
namespace: "bluetooth"
description: "There is no value in pretending we are exiting properly. This is a kill and we should express it this way when finishing the process"
diff --git a/floss/OWNERS b/floss/OWNERS
deleted file mode 100644
index a823e6e1dd..0000000000
--- a/floss/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_chromeos
diff --git a/floss/pandora/OWNERS b/floss/pandora/OWNERS
deleted file mode 100644
index ca4001b6d4..0000000000
--- a/floss/pandora/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Reviewers for /floss/pandora
-
-johnlai@google.com
-chharry@google.com
diff --git a/framework/OWNERS b/framework/OWNERS
deleted file mode 100644
index 40a43c47cb..0000000000
--- a/framework/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-hallstrom@google.com
-okamil@google.com
-siyuanh@google.com
-wescande@google.com
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt
index cdb9bf0670..ef922c92e1 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -369,6 +369,7 @@ package android.bluetooth {
public interface BluetoothDevicePicker {
field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_DEVICE_SELECTED = "android.bluetooth.devicepicker.action.DEVICE_SELECTED";
field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_LAUNCH = "android.bluetooth.devicepicker.action.LAUNCH";
+ field @FlaggedApi("com.android.bluetooth.flags.opp_device_picker_extra_intent_apis") public static final String EXTRA_DEVICE_PICKER_ORIGINAL_SEND_INTENT = "android.bluetooth.extra.DEVICE_PICKER_ORIGINAL_SEND_INTENT";
field public static final String EXTRA_FILTER_TYPE = "android.bluetooth.devicepicker.extra.FILTER_TYPE";
field public static final String EXTRA_LAUNCH_CLASS = "android.bluetooth.devicepicker.extra.DEVICE_PICKER_LAUNCH_CLASS";
field public static final String EXTRA_LAUNCH_PACKAGE = "android.bluetooth.devicepicker.extra.LAUNCH_PACKAGE";
diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java
index 40d1153581..1b37497323 100644
--- a/framework/java/android/bluetooth/BluetoothAdapter.java
+++ b/framework/java/android/bluetooth/BluetoothAdapter.java
@@ -3686,6 +3686,9 @@ public final class BluetoothAdapter {
if (mBluetoothLeScanner != null) {
mBluetoothLeScanner.cleanup();
}
+ if (mDistanceMeasurementManager != null) {
+ mDistanceMeasurementManager.cleanup();
+ }
}
} finally {
mServiceLock.writeLock().unlock();
diff --git a/framework/java/android/bluetooth/BluetoothDevicePicker.java b/framework/java/android/bluetooth/BluetoothDevicePicker.java
index ee788dae18..7e7cd6d6b7 100644
--- a/framework/java/android/bluetooth/BluetoothDevicePicker.java
+++ b/framework/java/android/bluetooth/BluetoothDevicePicker.java
@@ -18,6 +18,7 @@ package android.bluetooth;
import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import android.annotation.FlaggedApi;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -25,6 +26,8 @@ import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
+import com.android.bluetooth.flags.Flags;
+
/**
* A helper to show a system "Device Picker" activity to the user.
*
@@ -64,6 +67,14 @@ public interface BluetoothDevicePicker {
String EXTRA_LAUNCH_CLASS = "android.bluetooth.devicepicker.extra.DEVICE_PICKER_LAUNCH_CLASS";
/**
+ * Extra for the original ACTION_SEND or ACTION_SEND_MULTIPLE intent that triggered the BT
+ * sharing.
+ */
+ @FlaggedApi(Flags.FLAG_OPP_DEVICE_PICKER_EXTRA_INTENT_APIS)
+ String EXTRA_DEVICE_PICKER_ORIGINAL_SEND_INTENT =
+ "android.bluetooth.extra.DEVICE_PICKER_ORIGINAL_SEND_INTENT";
+
+ /**
* Broadcast when one BT device is selected from BT device picker screen. Selected {@link
* BluetoothDevice} is returned in extra data named {@link BluetoothDevice#EXTRA_DEVICE}.
*/
diff --git a/framework/java/android/bluetooth/OWNERS b/framework/java/android/bluetooth/OWNERS
deleted file mode 100644
index 757ed73819..0000000000
--- a/framework/java/android/bluetooth/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-per-file BluetoothHearingAid.java=file:/OWNERS_hearingaid
-per-file BluetoothCsipSetCoordinator.java=file:/OWNERS_leaudio
-per-file BluetoothLeAudio*.java=file:/OWNERS_leaudio
-per-file BluetoothLeBroadcast*.java=file:/OWNERS_leaudio
-per-file BluetoothVolumeControl.java=file:/OWNERS_leaudio
diff --git a/framework/java/android/bluetooth/le/DistanceMeasurementManager.java b/framework/java/android/bluetooth/le/DistanceMeasurementManager.java
index 3b3c1126ff..94715301f0 100644
--- a/framework/java/android/bluetooth/le/DistanceMeasurementManager.java
+++ b/framework/java/android/bluetooth/le/DistanceMeasurementManager.java
@@ -24,6 +24,7 @@ import static java.util.Objects.requireNonNull;
import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
@@ -271,6 +272,16 @@ public final class DistanceMeasurementManager {
return Collections.emptySet();
}
+ /**
+ * Clear session map. Should be called when bluetooth is down.
+ *
+ * @hide
+ */
+ @RequiresNoPermission
+ public void cleanup() {
+ mSessionMap.clear();
+ }
+
@SuppressLint("AndroidFrameworkBluetoothPermission")
private final IDistanceMeasurementCallback mCallbackWrapper =
new IDistanceMeasurementCallback.Stub() {
diff --git a/framework/tests/bumble/src/android/bluetooth/DckScanTest.kt b/framework/tests/bumble/src/android/bluetooth/DckScanTest.kt
index 8660a4076b..845862b71a 100644
--- a/framework/tests/bumble/src/android/bluetooth/DckScanTest.kt
+++ b/framework/tests/bumble/src/android/bluetooth/DckScanTest.kt
@@ -32,6 +32,7 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeout
import org.junit.Assume.assumeTrue
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -99,6 +100,7 @@ class DckScanTest(
}
@Test
+ @Ignore("b/404159990")
fun scanForUuid_remoteFound() {
// Assume isRemoteAdvertisingWithUuid is true to skip tests in which
// device is not advertising with UUID
diff --git a/framework/tests/bumble/src/android/bluetooth/GattClientTest.java b/framework/tests/bumble/src/android/bluetooth/GattClientTest.java
index 9b631dce91..6e6337279e 100644
--- a/framework/tests/bumble/src/android/bluetooth/GattClientTest.java
+++ b/framework/tests/bumble/src/android/bluetooth/GattClientTest.java
@@ -422,7 +422,6 @@ public class GattClientTest {
}
@Test
- @RequiresFlagsEnabled(Flags.FLAG_GATT_FIX_MULTIPLE_DIRECT_CONNECT)
public void connectMultiple_closeOne_shouldSuccess() {
BluetoothGattCallback gattCallback = mock(BluetoothGattCallback.class);
BluetoothGattCallback gattCallback2 = mock(BluetoothGattCallback.class);
@@ -435,11 +434,11 @@ public class GattClientTest {
BluetoothGatt gatt2 = device.connectGatt(mContext, false, gattCallback2);
try {
- gatt.disconnect();
- gatt.close();
-
verify(gattCallback2, timeout(1000))
.onConnectionStateChange(eq(gatt2), eq(GATT_SUCCESS), eq(STATE_CONNECTED));
+
+ gatt.disconnect();
+ gatt.close();
} finally {
gatt2.disconnect();
gatt2.close();
@@ -696,7 +695,6 @@ public class GattClientTest {
// Check if we can have 100 simultaneous clients
@Test
- @RequiresFlagsEnabled(Flags.FLAG_GATT_CLIENT_DYNAMIC_ALLOCATION)
public void connectGatt_multipleClients() {
registerGattService();
diff --git a/framework/tests/bumble/src/android/bluetooth/hid/HidHeadTrackerTest.java b/framework/tests/bumble/src/android/bluetooth/hid/HidHeadTrackerTest.java
index 38527362ba..3df5075936 100644
--- a/framework/tests/bumble/src/android/bluetooth/hid/HidHeadTrackerTest.java
+++ b/framework/tests/bumble/src/android/bluetooth/hid/HidHeadTrackerTest.java
@@ -64,6 +64,7 @@ import android.util.Log;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.bluetooth.flags.Flags;
import com.android.compatibility.common.util.AdoptShellPermissionsRule;
import org.hamcrest.CustomTypeSafeMatcher;
@@ -353,6 +354,7 @@ public class HidHeadTrackerTest {
BluetoothDevice.ACTION_UUID,
BluetoothDevice.ACTION_ACL_CONNECTED,
BluetoothDevice.ACTION_ACL_DISCONNECTED,
+ BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED,
BluetoothDevice.ACTION_FOUND);
}
@@ -405,6 +407,7 @@ public class HidHeadTrackerTest {
unregisterIntentActions(
BluetoothDevice.ACTION_UUID,
BluetoothDevice.ACTION_ACL_CONNECTED,
+ BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED,
BluetoothDevice.ACTION_FOUND);
}
@@ -490,8 +493,10 @@ public class HidHeadTrackerTest {
*/
private void verifyTransportSwitch(BluetoothDevice device, int fromTransport, int toTransport) {
assertThat(fromTransport).isNotEqualTo(toTransport);
- verifyConnectionState(mBumbleDevice, equalTo(fromTransport), equalTo(STATE_DISCONNECTING));
-
+ if (!Flags.ignoreUnselectedHidTransportStates()) {
+ verifyConnectionState(
+ mBumbleDevice, equalTo(fromTransport), equalTo(STATE_DISCONNECTING));
+ }
// Capture the next intent with filter
// Filter is necessary as otherwise it will corrupt all other unordered verifications
final Intent[] savedIntent = {null};
diff --git a/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java b/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java
index fb89c738ad..45c329e460 100644
--- a/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java
+++ b/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java
@@ -66,6 +66,7 @@ import android.util.Log;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.bluetooth.flags.Flags;
import com.android.compatibility.common.util.AdoptShellPermissionsRule;
import org.hamcrest.CustomTypeSafeMatcher;
@@ -503,8 +504,9 @@ public class HidHostDualModeTest {
*/
private void verifyTransportSwitch(BluetoothDevice device, int fromTransport, int toTransport) {
assertThat(fromTransport).isNotEqualTo(toTransport);
- verifyConnectionState(mDevice, equalTo(fromTransport), equalTo(STATE_DISCONNECTING));
-
+ if (!Flags.ignoreUnselectedHidTransportStates()) {
+ verifyConnectionState(mDevice, equalTo(fromTransport), equalTo(STATE_DISCONNECTING));
+ }
// Capture the next intent with filter
// Filter is necessary as otherwise it will corrupt all other unordered verifications
final Intent[] savedIntent = {null};
diff --git a/framework/tests/bumble/src/android/bluetooth/hid/OWNERS b/framework/tests/bumble/src/android/bluetooth/hid/OWNERS
deleted file mode 100644
index 75539edb09..0000000000
--- a/framework/tests/bumble/src/android/bluetooth/hid/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 27441
-# Project owners
-rwt@google.com
diff --git a/framework/tests/bumble/src/android/bluetooth/pairing/OWNERS b/framework/tests/bumble/src/android/bluetooth/pairing/OWNERS
deleted file mode 100644
index 75539edb09..0000000000
--- a/framework/tests/bumble/src/android/bluetooth/pairing/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 27441
-# Project owners
-rwt@google.com
diff --git a/framework/tests/bumble/src/android/bluetooth/pairing/OobPairingTest.java b/framework/tests/bumble/src/android/bluetooth/pairing/OobPairingTest.java
index bdfa42dd65..0b0da56f7b 100644
--- a/framework/tests/bumble/src/android/bluetooth/pairing/OobPairingTest.java
+++ b/framework/tests/bumble/src/android/bluetooth/pairing/OobPairingTest.java
@@ -19,6 +19,8 @@ package android.bluetooth.pairing;
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction;
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra;
+import static com.google.common.truth.Truth.assertThat;
+
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothAdapter.OobDataCallback;
import android.bluetooth.BluetoothDevice;
@@ -340,11 +342,14 @@ public class OobPairingTest {
while (true) {
if (scanningResponseIterator.hasNext()) {
ScanningResponse scanningResponse = scanningResponseIterator.next();
- // select first available device
+ // select first available device with Random address type
deviceAddr = scanningResponse.getRandom();
- break;
+ if (deviceAddr != null) {
+ break;
+ }
}
}
+ assertThat(deviceAddr).isNotNull();
ConnectLEResponse leConn =
mBumble.hostBlocking()
diff --git a/framework/tests/bumble/src/android/bluetooth/service_discovery/OWNERS b/framework/tests/bumble/src/android/bluetooth/service_discovery/OWNERS
deleted file mode 100644
index 353b5d03a5..0000000000
--- a/framework/tests/bumble/src/android/bluetooth/service_discovery/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 27441
-# Project owners
-jpawlowski@google.com
diff --git a/framework/tests/bumble/src/android/bluetooth/sockets/OWNERS b/framework/tests/bumble/src/android/bluetooth/sockets/OWNERS
deleted file mode 100644
index f9b588d2e9..0000000000
--- a/framework/tests/bumble/src/android/bluetooth/sockets/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Project owners
-bhaktha@google.com
-poahlo@google.com
diff --git a/framework/tests/metrics/OWNERS b/framework/tests/metrics/OWNERS
deleted file mode 100644
index 01d41baf7e..0000000000
--- a/framework/tests/metrics/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 1099313
-# Project owners
-ahujapalash@google.com
diff --git a/offload/leaudio/hci/proxy.rs b/offload/leaudio/hci/proxy.rs
index 933389d315..adc2dbd34d 100644
--- a/offload/leaudio/hci/proxy.rs
+++ b/offload/leaudio/hci/proxy.rs
@@ -195,10 +195,16 @@ impl Module for LeAudioModule {
);
}
- Ok(Command::LeSetupIsoDataPath(ref c)) if c.data_path_id == DATA_PATH_ID_SOFTWARE => {
+ Ok(Command::LeSetupIsoDataPath(ref c)) if c.data_path_id == DATA_PATH_ID_SOFTWARE => 'command: {
assert_eq!(c.data_path_direction, hci::LeDataPathDirection::Input);
let mut state = self.state.lock().unwrap();
- let stream = state.stream.get_mut(&c.connection_handle).unwrap();
+ let Some(stream) = state.stream.get_mut(&c.connection_handle) else {
+ log::warn!(
+ "Setup ISO Data Path on non existing BIS/CIS handle: 0x{:03x}",
+ c.connection_handle
+ );
+ break 'command;
+ };
stream.state = StreamState::Enabling;
// Phase 1 limitation: The controller does not implement HCI Link Feedback event,
@@ -209,6 +215,16 @@ impl Module for LeAudioModule {
return;
}
+ Ok(Command::LeRemoveIsoDataPath(ref c)) => {
+ let mut state = self.state.lock().unwrap();
+ if state.stream.get_mut(&c.connection_handle).is_none() {
+ log::warn!(
+ "Remove ISO Data Path on non existing BIS/CIS handle: 0x{:03x}",
+ c.connection_handle
+ );
+ }
+ }
+
_ => (),
}
@@ -250,7 +266,9 @@ impl Module for LeAudioModule {
ReturnParameters::LeSetupIsoDataPath(ref ret) => 'event: {
let mut state = self.state.lock().unwrap();
- let stream = state.stream.get_mut(&ret.connection_handle).unwrap();
+ let Some(stream) = state.stream.get_mut(&ret.connection_handle) else {
+ break 'event;
+ };
stream.state =
if stream.state == StreamState::Enabling && ret.status == Status::Success {
StreamState::Enabled
@@ -278,9 +296,11 @@ impl Module for LeAudioModule {
);
}
- ReturnParameters::LeRemoveIsoDataPath(ref ret) if ret.status == Status::Success => {
+ ReturnParameters::LeRemoveIsoDataPath(ref ret) if ret.status == Status::Success => 'event: {
let mut state = self.state.lock().unwrap();
- let stream = state.stream.get_mut(&ret.connection_handle).unwrap();
+ let Some(stream) = state.stream.get_mut(&ret.connection_handle) else {
+ break 'event;
+ };
if stream.state == StreamState::Enabled {
Service::stop_stream(ret.connection_handle);
}
diff --git a/pandora/OWNERS b/pandora/OWNERS
deleted file mode 100644
index 14634f3b78..0000000000
--- a/pandora/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Project owners
-girardier@google.com
diff --git a/service/OWNERS b/service/OWNERS
deleted file mode 100644
index 5b3f4bad26..0000000000
--- a/service/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-wescande@google.com
diff --git a/service/src/com/android/server/bluetooth/BluetoothManagerService.java b/service/src/com/android/server/bluetooth/BluetoothManagerService.java
index 08a949d81a..b797d6ceac 100644
--- a/service/src/com/android/server/bluetooth/BluetoothManagerService.java
+++ b/service/src/com/android/server/bluetooth/BluetoothManagerService.java
@@ -78,7 +78,6 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.sysprop.BluetoothProperties;
-import android.util.proto.ProtoOutputStream;
import androidx.annotation.RequiresApi;
@@ -95,7 +94,6 @@ import kotlin.Unit;
import kotlin.time.TimeSource;
import java.io.FileDescriptor;
-import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -140,10 +138,17 @@ class BluetoothManagerService {
// Delay for retrying enable and disable in msec
@VisibleForTesting static final int ENABLE_DISABLE_DELAY_MS = 300 * HW_MULTIPLIER;
+ // TODO: b/402209603 remove along with system_server_remove_extra_thread_jump
@VisibleForTesting static final int MESSAGE_ENABLE = 1;
+ // TODO: b/402209603 remove along with system_server_remove_extra_thread_jump
@VisibleForTesting static final int MESSAGE_DISABLE = 2;
+
+ // TODO: b/402209603 remove along with system_server_remove_extra_thread_jump
@VisibleForTesting static final int MESSAGE_HANDLE_ENABLE_DELAYED = 3;
+
+ // TODO: b/402209603 remove along with system_server_remove_extra_thread_jump
@VisibleForTesting static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4;
+
@VisibleForTesting static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40;
@VisibleForTesting static final int MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED = 41;
@VisibleForTesting static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42;
@@ -327,8 +332,9 @@ class BluetoothManagerService {
} else if (state != STATE_ON && state != STATE_OFF && state != STATE_BLE_ON) {
// Bluetooth is turning state
return ADD_PROXY_DELAY_MS;
- } else if (mHandler.hasMessages(MESSAGE_ENABLE)
- || mHandler.hasMessages(MESSAGE_DISABLE)
+ } else if ((!Flags.systemServerRemoveExtraThreadJump()
+ && (mHandler.hasMessages(MESSAGE_ENABLE)
+ || mHandler.hasMessages(MESSAGE_DISABLE)))
|| mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)
|| mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED)
|| mHandler.hasMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE)
@@ -1038,6 +1044,42 @@ class BluetoothManagerService {
return true;
}
+ private static CompletableFuture<Void> createDeathNotifier(IBinder binder) {
+ CompletableFuture<Void> deathNotifier = new CompletableFuture<>();
+ try {
+ binder.linkToDeath(
+ () -> {
+ Log.i(TAG, "Successfully received Bluetooth death");
+ deathNotifier.complete(null);
+ },
+ 0);
+ } catch (RemoteException e) {
+ Log.e(TAG, "listenBinderDeath(): Failed to linkToDeath", e);
+ deathNotifier.complete(null);
+ }
+ return deathNotifier;
+ }
+
+ private static void killBluetoothProcess(
+ AdapterBinder adapter, CompletableFuture<Void> deathNotifier) {
+ try {
+ // Force kill Bluetooth to make sure its process is not reused.
+ // Note: In a perfect world, we should be able to re-init the same process.
+ // Unfortunately, this requires an heavy rework of the Bluetooth app
+ // TODO: b/339501753 - Properly stop Bluetooth without killing it
+ adapter.killBluetoothProcess();
+
+ deathNotifier.get(2_000, TimeUnit.MILLISECONDS);
+ } catch (android.os.DeadObjectException e) {
+ // Reduce exception to info and skip waiting (Bluetooth is dead as wanted)
+ Log.i(TAG, "killBluetoothProcess(): Bluetooth already dead 💀");
+ } catch (RemoteException e) {
+ Log.e(TAG, "killBluetoothProcess(): Unable to call killBluetoothProcess", e);
+ } catch (TimeoutException | InterruptedException | ExecutionException e) {
+ Log.e(TAG, "killBluetoothProcess(): Bluetooth death not received after > 2000ms", e);
+ }
+ }
+
void unbindAndFinish() {
Log.d(TAG, "unbindAndFinish(): mAdapter=" + mAdapter + " isBinding=" + isBinding());
@@ -1054,40 +1096,13 @@ class BluetoothManagerService {
Log.e(TAG, "unbindAndFinish(): Unable to unregister BluetoothCallback", e);
}
- CompletableFuture<Void> binderDead = new CompletableFuture<>();
- try {
- mAdapter.getAdapterBinder()
- .asBinder()
- .linkToDeath(
- () -> {
- Log.i(TAG, "Successfully received Bluetooth death");
- binderDead.complete(null);
- },
- 0);
- } catch (RemoteException e) {
- Log.e(TAG, "unbindAndFinish(): Failed to linkToDeath", e);
- binderDead.complete(null);
- }
+ CompletableFuture<Void> deathNotifier =
+ createDeathNotifier(mAdapter.getAdapterBinder().asBinder());
// Unbind first to avoid receiving unwanted "onServiceDisconnected"
mContext.unbindService(mConnection);
- try {
- // Force kill Bluetooth to make sure its process is not reused.
- // Note: In a perfect world, we should be able to re-init the same process.
- // Unfortunately, this requires an heavy rework of the Bluetooth app
- // TODO: b/339501753 - Properly stop Bluetooth without killing it
- mAdapter.killBluetoothProcess();
-
- binderDead.get(2_000, TimeUnit.MILLISECONDS);
- } catch (android.os.DeadObjectException e) {
- // Reduce exception to info and skip waiting (Bluetooth is dead as wanted)
- Log.i(TAG, "unbindAndFinish(): Bluetooth already dead 💀");
- } catch (RemoteException e) {
- Log.e(TAG, "unbindAndFinish(): Unable to call killBluetoothProcess", e);
- } catch (TimeoutException | InterruptedException | ExecutionException e) {
- Log.e(TAG, "unbindAndFinish(): Bluetooth death not received after > 2000ms", e);
- }
+ killBluetoothProcess(mAdapter, deathNotifier);
long timeSpentForShutdown = System.currentTimeMillis() - currentTimeMs;
mShutdownLatencyHistogram.logSample((float) timeSpentForShutdown);
@@ -1228,10 +1243,10 @@ class BluetoothManagerService {
}
if (Flags.setComponentAvailableFix()) {
- mHandler
- .obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED,
- componentName.getPackageName())
- .sendToTarget();
+ mHandler.obtainMessage(
+ MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED,
+ componentName.getPackageName())
+ .sendToTarget();
} else {
mHandler.sendEmptyMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
}
@@ -1252,8 +1267,12 @@ class BluetoothManagerService {
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_ENABLE:
- int quietEnable = msg.arg1;
- int isBle = msg.arg2;
+ if (Flags.systemServerRemoveExtraThreadJump()) {
+ break;
+ }
+
+ boolean quietEnable = msg.arg1 != 0;
+ boolean isBle = msg.arg2 != 0;
Log.d(
TAG,
@@ -1265,6 +1284,10 @@ class BluetoothManagerService {
break;
case MESSAGE_DISABLE:
+ if (Flags.systemServerRemoveExtraThreadJump()) {
+ break;
+ }
+
Log.d(TAG, "MESSAGE_DISABLE: mAdapter=" + mAdapter);
handleDisableMessage();
@@ -1311,6 +1334,15 @@ class BluetoothManagerService {
case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
IBinder service = (IBinder) msg.obj;
+
+ // Handle case where disable was called before binding complete.
+ if (Flags.systemServerRemoveExtraThreadJump() && !isBinding() && !mEnable) {
+ Log.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_CONNECTED: after cancelling binding");
+ AdapterBinder adapter =
+ BluetoothServerProxy.getInstance().createAdapterBinder(service);
+ killBluetoothProcess(adapter, createDeathNotifier(service));
+ break;
+ }
Log.d(TAG, "MESSAGE_BLUETOOTH_SERVICE_CONNECTED: service=" + service);
// Remove timeout
@@ -1330,7 +1362,7 @@ class BluetoothManagerService {
offToBleOn();
sendBluetoothServiceUpCallback();
- if (!mEnable) {
+ if (!Flags.systemServerRemoveExtraThreadJump() && !mEnable) {
waitForState(STATE_ON);
onToBleOn();
}
@@ -1359,13 +1391,31 @@ class BluetoothManagerService {
}
// If we tried to enable BT while BT was in the process of shutting down,
// wait for the BT process to fully tear down and then force a restart
- // here. This is a bit of a hack (b/29363429).
+ // here. This is a bit of a hack (b/29363429).
if (prevState == STATE_BLE_TURNING_OFF && newState == STATE_OFF) {
- if (mEnable) {
- Log.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting.");
- waitForState(STATE_OFF);
- mHandler.sendEmptyMessageDelayed(
- MESSAGE_RESTART_BLUETOOTH_SERVICE, getServiceRestartMs());
+ if (Flags.enableBleWhileDisablingAirplane()) {
+ if (mHandler.hasMessages(0, ON_AIRPLANE_MODE_CHANGED_TOKEN)) {
+ mHandler.removeCallbacksAndMessages(ON_AIRPLANE_MODE_CHANGED_TOKEN);
+ Log.d(TAG, "Handling delayed airplane mode event");
+ handleAirplaneModeChanged(AirplaneModeListener.isOnOverrode());
+ }
+ if (mEnable && !isBinding()) {
+ Log.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting.");
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ waitForState(STATE_OFF);
+ }
+ mHandler.sendEmptyMessageDelayed(
+ MESSAGE_RESTART_BLUETOOTH_SERVICE, getServiceRestartMs());
+ }
+ } else {
+ if (mEnable) {
+ Log.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting.");
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ waitForState(STATE_OFF);
+ }
+ mHandler.sendEmptyMessageDelayed(
+ MESSAGE_RESTART_BLUETOOTH_SERVICE, getServiceRestartMs());
+ }
}
}
if (newState == STATE_ON || newState == STATE_BLE_ON) {
@@ -1524,17 +1574,19 @@ class BluetoothManagerService {
return mHandler.hasMessages(MESSAGE_TIMEOUT_BIND);
}
- private void handleEnableMessage(int quietEnable, int isBle) {
+ private void handleEnableMessage(boolean quietEnable, boolean isBle) {
+ String logHeader = "handleEnableMessage(" + quietEnable + ", " + isBle + "): ";
if (mShutdownInProgress) {
- Log.d(TAG, "Skip Bluetooth Enable in device shutdown process");
+ Log.d(TAG, logHeader + "Skip Bluetooth Enable in device shutdown process");
return;
}
- if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED)
- || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) {
+ if (!Flags.systemServerRemoveExtraThreadJump()
+ && (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED)
+ || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED))) {
// We are handling enable or disable right now, wait for it.
mHandler.sendMessageDelayed(
- mHandler.obtainMessage(MESSAGE_ENABLE, quietEnable, isBle),
+ mHandler.obtainMessage(MESSAGE_ENABLE, quietEnable ? 1 : 0, isBle ? 1 : 0),
ENABLE_DISABLE_DELAY_MS);
return;
}
@@ -1542,27 +1594,27 @@ class BluetoothManagerService {
mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
mEnable = true;
- if (isBle == 0) {
+ if (!isBle) {
setBluetoothPersistedState(BLUETOOTH_ON_BLUETOOTH);
}
if (mState.oneOf(STATE_BLE_TURNING_ON, STATE_TURNING_ON, STATE_ON)) {
- Log.i(TAG, "MESSAGE_ENABLE: already enabled. Current state=" + mState);
+ Log.i(TAG, logHeader + "Already enabled. Current state=" + mState);
return;
}
- if (mState.oneOf(STATE_BLE_ON) && isBle == 1) {
- Log.i(TAG, "MESSAGE_ENABLE: Already in BLE_ON while being requested to go to BLE_ON");
+ if (mState.oneOf(STATE_BLE_ON) && isBle) {
+ Log.i(TAG, logHeader + "Already in BLE_ON while being requested to go to BLE_ON");
return;
}
if (mState.oneOf(STATE_BLE_ON)) {
- Log.i(TAG, "MESSAGE_ENABLE: Bluetooth transition from STATE_BLE_ON to STATE_ON");
+ Log.i(TAG, logHeader + "Bluetooth transition from STATE_BLE_ON to STATE_ON");
bleOnToOn();
return;
}
- if (mAdapter != null) {
+ if (!Flags.systemServerRemoveExtraThreadJump() && mAdapter != null) {
// TODO: b/339548431 - Adapt this after removal of Flags.explicitKillFromSystemServer
//
// We need to wait until transitioned to STATE_OFF and the previous Bluetooth process
@@ -1581,14 +1633,15 @@ class BluetoothManagerService {
return;
}
- mQuietEnable = (quietEnable == 1);
+ mQuietEnable = quietEnable;
handleEnable();
}
private void handleDisableMessage() {
- if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED)
- || isBinding()
- || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) {
+ if (!Flags.systemServerRemoveExtraThreadJump()
+ && (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED)
+ || isBinding()
+ || mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED))) {
// We are handling enable or disable right now, wait for it.
mHandler.sendEmptyMessageDelayed(MESSAGE_DISABLE, ENABLE_DISABLE_DELAY_MS);
return;
@@ -1596,10 +1649,25 @@ class BluetoothManagerService {
mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
- if (mEnable && mAdapter != null) {
+ if (Flags.systemServerRemoveExtraThreadJump() && isBinding()) {
+ Log.d(TAG, "Disable while binding");
+ mEnable = false;
+ mContext.unbindService(mConnection);
+ mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
+ mHandler.removeMessages(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
+ } else if (Flags.systemServerRemoveExtraThreadJump()
+ && mState.oneOf(STATE_BLE_TURNING_ON)) {
+ Log.d(TAG, "Disable while BLE_TURNING_ON");
+ mEnable = false;
+ bluetoothStateChangeHandler(STATE_BLE_TURNING_ON, STATE_OFF);
+ } else if (mEnable && mAdapter != null) {
mWaitForDisableRetry = 0;
- mHandler.sendEmptyMessageDelayed(
- MESSAGE_HANDLE_DISABLE_DELAYED, ENABLE_DISABLE_DELAY_MS);
+ if (Flags.systemServerRemoveExtraThreadJump()) {
+ handleDisableDelayed(false);
+ } else {
+ mHandler.sendEmptyMessageDelayed(
+ MESSAGE_HANDLE_DISABLE_DELAYED, ENABLE_DISABLE_DELAY_MS);
+ }
} else {
mEnable = false;
onToBleOn();
@@ -1648,6 +1716,10 @@ class BluetoothManagerService {
Log.e(TAG, "Wait for STATE_OFF timeout");
}
}
+ if (Flags.systemServerRemoveExtraThreadJump()) {
+ handleEnable();
+ return;
+ }
// Either state is changed to STATE_OFF or reaches the maximum retry, we
// should move forward to the next step.
mWaitForEnableRetry = 0;
@@ -1656,6 +1728,9 @@ class BluetoothManagerService {
}
private void handleDisableDelayed(boolean disabling) {
+ if (Flags.systemServerRemoveExtraThreadJump() && disabling) {
+ return;
+ }
if (!disabling) {
// The Bluetooth is turning on, wait for STATE_ON
if (!mState.oneOf(STATE_ON)) {
@@ -1673,10 +1748,12 @@ class BluetoothManagerService {
mWaitForDisableRetry = 0;
mEnable = false;
onToBleOn();
- // Wait for state exiting STATE_ON
- Message disableDelayedMsg =
- mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0);
- mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS);
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ // Wait for state exiting STATE_ON
+ Message disableDelayedMsg =
+ mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0);
+ mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS);
+ }
} else {
// The Bluetooth is turning off, wait for exiting STATE_ON
if (mState.oneOf(STATE_ON)) {
@@ -1837,8 +1914,13 @@ class BluetoothManagerService {
}
private void sendDisableMsg(int reason, String packageName) {
- mHandler.sendEmptyMessage(MESSAGE_DISABLE);
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ mHandler.sendEmptyMessage(MESSAGE_DISABLE);
+ }
ActiveLogs.add(reason, false, packageName, false);
+ if (Flags.systemServerRemoveExtraThreadJump()) {
+ handleDisableMessage();
+ }
}
private void sendEnableMsg(boolean quietMode, int reason) {
@@ -1850,9 +1932,14 @@ class BluetoothManagerService {
}
private void sendEnableMsg(boolean quietMode, int reason, String packageName, boolean isBle) {
- mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, isBle ? 1 : 0).sendToTarget();
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, isBle ? 1 : 0).sendToTarget();
+ }
ActiveLogs.add(reason, true, packageName, isBle);
mLastEnabledTime = SystemClock.elapsedRealtime();
+ if (Flags.systemServerRemoveExtraThreadJump()) {
+ handleEnableMessage(quietMode, isBle);
+ }
}
private void addCrashLog() {
@@ -2254,33 +2341,34 @@ class BluetoothManagerService {
}
/**
- * In case of a Bluetooth crash, mark it's enabled components as non longer available to
- * trigger the PACKAGE_CHANGED intent. This should not be needed in a normal shutdown as the
- * Bluetooth clean its components on its own
+ * In case of a Bluetooth crash, mark it's enabled components as non longer available to trigger
+ * the PACKAGE_CHANGED intent. This should not be needed in a normal shutdown as the Bluetooth
+ * clean its components on its own
*/
private void disableBluetoothComponents(String packageName) {
PackageManager pm = mContext.getPackageManager();
PackageInfo packageInfo = null;
try {
- packageInfo = pm.getPackageInfo(
- packageName,
- PackageManager.GET_SERVICES |
- PackageManager.GET_ACTIVITIES |
- PackageManager.GET_RECEIVERS |
- PackageManager.GET_PROVIDERS);
+ packageInfo =
+ pm.getPackageInfo(
+ packageName,
+ PackageManager.GET_SERVICES
+ | PackageManager.GET_ACTIVITIES
+ | PackageManager.GET_RECEIVERS
+ | PackageManager.GET_PROVIDERS);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "Package not found: " + packageName, e);
return;
}
// Refer to updateOppLauncherComponentState()
- List<String> baseBluetoothOppActivities = List.of(
- "com.android.bluetooth.opp.BluetoothOppLauncherActivity",
- "com.android.bluetooth.opp.BluetoothOppBtEnableActivity",
- "com.android.bluetooth.opp.BluetoothOppBtEnablingActivity",
- "com.android.bluetooth.opp.BluetoothOppBtErrorActivity"
- );
+ List<String> baseBluetoothOppActivities =
+ List.of(
+ "com.android.bluetooth.opp.BluetoothOppLauncherActivity",
+ "com.android.bluetooth.opp.BluetoothOppBtEnableActivity",
+ "com.android.bluetooth.opp.BluetoothOppBtEnablingActivity",
+ "com.android.bluetooth.opp.BluetoothOppBtErrorActivity");
disableComponents(pm, packageInfo.activities, packageName, baseBluetoothOppActivities);
disableComponents(pm, packageInfo.services, packageName, null);
@@ -2295,17 +2383,20 @@ class BluetoothManagerService {
}
Arrays.stream(components)
- .filter(componentInfo -> !componentInfo.enabled)
- .map(componentInfo -> new ComponentName(packageName, componentInfo.name))
- .filter(componentName ->
- (componentsToKeep == null ||
- !componentsToKeep.contains(componentName.getClassName())))
- .forEach(componentName -> {
- pm.setComponentEnabledSetting(
- componentName,
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
- Log.i(TAG, "Disabled component: " + componentName.flattenToString());
- });
+ .filter(componentInfo -> !componentInfo.enabled)
+ .map(componentInfo -> new ComponentName(packageName, componentInfo.name))
+ .filter(
+ componentName ->
+ (componentsToKeep == null
+ || !componentsToKeep.contains(
+ componentName.getClassName())))
+ .forEach(
+ componentName -> {
+ pm.setComponentEnabledSetting(
+ componentName,
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP);
+ Log.i(TAG, "Disabled component: " + componentName.flattenToString());
+ });
}
}
diff --git a/service/tests/Android.bp b/service/tests/Android.bp
index 217bd36f70..8bdefcc8ac 100644
--- a/service/tests/Android.bp
+++ b/service/tests/Android.bp
@@ -26,6 +26,7 @@ android_test {
],
static_libs: [
+ "androidx.test.espresso.intents",
"androidx.test.rules",
"flag-junit",
"frameworks-base-testutils",
diff --git a/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java b/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java
index 480af98329..e825940e90 100644
--- a/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java
+++ b/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java
@@ -22,6 +22,9 @@ import static android.bluetooth.BluetoothAdapter.STATE_ON;
import static android.bluetooth.BluetoothAdapter.STATE_TURNING_OFF;
import static android.bluetooth.BluetoothAdapter.STATE_TURNING_ON;
+import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction;
+import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra;
+
import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_BLUETOOTH_SERVICE_CONNECTED;
import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED;
import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_BLUETOOTH_STATE_CHANGE;
@@ -33,6 +36,7 @@ import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_RESTO
import static com.android.server.bluetooth.BluetoothManagerService.MESSAGE_TIMEOUT_BIND;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
@@ -41,13 +45,16 @@ import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.validateMockitoUsage;
import static org.mockito.Mockito.verify;
import android.annotation.SuppressLint;
+import android.app.AppOpsManager;
import android.app.PropertyInvalidatedCache;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.IBluetooth;
import android.bluetooth.IBluetoothCallback;
import android.bluetooth.IBluetoothManager;
@@ -55,7 +62,6 @@ import android.bluetooth.IBluetoothManagerCallback;
import android.bluetooth.IBluetoothStateChangeCallback;
import android.content.ComponentName;
import android.content.Context;
-import android.content.ContextWrapper;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
@@ -63,21 +69,29 @@ import android.os.Message;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.test.TestLooper;
+import android.permission.PermissionManager;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.FlagsParameterization;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.bluetooth.flags.Flags;
+
+import org.hamcrest.Matcher;
+import org.hamcrest.core.AllOf;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.mockito.Spy;
+import org.mockito.hamcrest.MockitoHamcrest;
import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
import platform.test.runner.parameterized.Parameters;
@@ -93,7 +107,8 @@ public class BluetoothManagerServiceTest {
@Parameters(name = "{0}")
public static List<FlagsParameterization> getParams() {
- return FlagsParameterization.allCombinationsOf();
+ return FlagsParameterization.allCombinationsOf(
+ Flags.FLAG_SYSTEM_SERVER_REMOVE_EXTRA_THREAD_JUMP);
}
public BluetoothManagerServiceTest(FlagsParameterization flags) {
@@ -103,24 +118,26 @@ public class BluetoothManagerServiceTest {
private static final int STATE_BLE_TURNING_ON = 14; // can't find the symbol because hidden api
private static final int STATE_BLE_TURNING_OFF = 16; // can't find the symbol because hidden api
- BluetoothManagerService mManagerService;
+ private final Context mTargetContext =
+ InstrumentationRegistry.getInstrumentation().getTargetContext();
- @Spy
- private final Context mContext =
- new ContextWrapper(InstrumentationRegistry.getInstrumentation().getTargetContext());
-
- @Spy BluetoothServerProxy mBluetoothServerProxy;
+ @Mock BluetoothServerProxy mBluetoothServerProxy;
+ @Mock Context mContext;
@Mock UserManager mUserManager;
@Mock UserHandle mUserHandle;
-
@Mock IBinder mBinder;
@Mock IBluetoothManagerCallback mManagerCallback;
@Mock IBluetoothStateChangeCallback mStateChangeCallback;
-
@Mock IBluetooth mAdapterService;
@Mock AdapterBinder mAdapterBinder;
+ @Mock AppOpsManager mAppOpsManager;
+ @Mock PermissionManager mPermissionManager;
+
+ private int mPersistedState = BluetoothManagerService.BLUETOOTH_OFF;
- TestLooper mLooper;
+ private InOrder mInOrder;
+ private TestLooper mLooper;
+ private BluetoothManagerService mManagerService;
private static class ServerQuery
extends PropertyInvalidatedCache.QueryHandler<IBluetoothManager, Integer> {
@@ -146,6 +163,7 @@ public class BluetoothManagerServiceTest {
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ mInOrder = inOrder(mContext, mManagerCallback, mAdapterBinder);
PropertyInvalidatedCache<IBluetoothManager, Integer> testCache =
new PropertyInvalidatedCache<>(
@@ -163,24 +181,37 @@ public class BluetoothManagerServiceTest {
doReturn("00:11:22:33:44:55")
.when(mBluetoothServerProxy)
.settingsSecureGetString(any(), eq(Settings.Secure.BLUETOOTH_ADDRESS));
- // Set persisted state to BLUETOOTH_OFF to not generate unwanted behavior when starting test
- doReturn(BluetoothManagerService.BLUETOOTH_OFF)
+ doAnswer(
+ inv -> {
+ return mPersistedState;
+ })
.when(mBluetoothServerProxy)
.getBluetoothPersistedState(any(), anyInt());
doAnswer(
inv -> {
- doReturn(inv.getArguments()[1])
- .when(mBluetoothServerProxy)
- .getBluetoothPersistedState(any(), anyInt());
+ mPersistedState = inv.getArgument(1);
return null;
})
.when(mBluetoothServerProxy)
.setBluetoothPersistedState(any(), anyInt());
- // Test is not allowed to send broadcast as Bluetooth. doNothing Prevent SecurityException
- doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any(), any());
+ doAnswer(
+ inv -> {
+ IBinder.DeathRecipient recipient = inv.getArgument(0);
+ recipient.binderDied();
+ return null;
+ })
+ .when(mBinder)
+ .linkToDeath(any(), anyInt());
+
+ doReturn(BluetoothManagerServiceTest.class.getSimpleName()).when(mContext).getPackageName();
+ doReturn(mContext).when(mContext).createContextAsUser(any(), anyInt());
+ doReturn(mTargetContext.getContentResolver()).when(mContext).getContentResolver();
+ doReturn(mTargetContext.getPackageManager()).when(mContext).getPackageManager();
doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
+ doReturn(mAppOpsManager).when(mContext).getSystemService(AppOpsManager.class);
+ doReturn(mPermissionManager).when(mContext).getSystemService(PermissionManager.class);
doReturn(mBinder).when(mManagerCallback).asBinder();
@@ -233,9 +264,13 @@ public class BluetoothManagerServiceTest {
IntStream.of(what)
.forEach(
w -> {
+ String log = "Expecting message " + w + ": ";
+
Message msg = mLooper.nextMessage();
- assertThat(msg).isNotNull();
- assertThat(msg.what).isEqualTo(w);
+ assertWithMessage(log + "but got null").that(msg).isNotNull();
+ assertWithMessage(log + "but got " + msg.what)
+ .that(msg.what)
+ .isEqualTo(w);
msg.getTarget().dispatchMessage(msg);
});
}
@@ -270,7 +305,9 @@ public class BluetoothManagerServiceTest {
// called from SYSTEM user, should try to toggle Bluetooth off
mManagerService.onUserRestrictionsChanged(UserHandle.SYSTEM);
- syncHandler(MESSAGE_DISABLE);
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ syncHandler(MESSAGE_DISABLE);
+ }
}
@Test
@@ -283,8 +320,11 @@ public class BluetoothManagerServiceTest {
anyInt(),
any(UserHandle.class));
mManagerService.enableBle("enable_bindFailure_removesTimeout", mBinder);
- syncHandler(MESSAGE_ENABLE);
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ syncHandler(MESSAGE_ENABLE);
+ }
verify(mContext).unbindService(any());
+ mInOrder.verify(mContext).unbindService(any());
// TODO(b/280518177): Failed to start should be noted / reported in metrics
// Maybe show a popup or a crash notification
@@ -294,7 +334,9 @@ public class BluetoothManagerServiceTest {
@Test
public void enable_bindTimeout() throws Exception {
mManagerService.enableBle("enable_bindTimeout", mBinder);
- syncHandler(MESSAGE_ENABLE);
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ syncHandler(MESSAGE_ENABLE);
+ }
mLooper.moveTimeForward(120_000); // 120 seconds
syncHandler(MESSAGE_TIMEOUT_BIND);
@@ -312,7 +354,7 @@ public class BluetoothManagerServiceTest {
ArgumentCaptor<BluetoothManagerService.BluetoothServiceConnection> captor =
ArgumentCaptor.forClass(BluetoothManagerService.BluetoothServiceConnection.class);
- verify(mContext)
+ mInOrder.verify(mContext)
.bindServiceAsUser(
any(Intent.class), captor.capture(), anyInt(), any(UserHandle.class));
assertThat(captor.getAllValues()).hasSize(1);
@@ -324,11 +366,10 @@ public class BluetoothManagerServiceTest {
return serviceConnection;
}
- private static IBluetoothCallback captureBluetoothCallback(AdapterBinder adapterBinder)
- throws Exception {
+ private IBluetoothCallback captureBluetoothCallback() throws Exception {
ArgumentCaptor<IBluetoothCallback> captor =
ArgumentCaptor.forClass(IBluetoothCallback.class);
- verify(adapterBinder).registerCallback(captor.capture(), any());
+ mInOrder.verify(mAdapterBinder).registerCallback(captor.capture(), any());
assertThat(captor.getAllValues()).hasSize(1);
return captor.getValue();
}
@@ -337,11 +378,10 @@ public class BluetoothManagerServiceTest {
// Binding of IBluetooth
acceptBluetoothBinding();
- // TODO(b/280518177): This callback is too early, bt is not ON nor BLE_ON
- verify(mManagerCallback).onBluetoothServiceUp(any());
-
- IBluetoothCallback btCallback = captureBluetoothCallback(mAdapterBinder);
- verify(mAdapterBinder).offToBleOn(anyBoolean(), any());
+ IBluetoothCallback btCallback = captureBluetoothCallback();
+ mInOrder.verify(mAdapterBinder).offToBleOn(anyBoolean(), any());
+ verifyBleStateIntentSent(STATE_OFF, STATE_BLE_TURNING_ON);
+ mInOrder.verify(mManagerCallback).onBluetoothServiceUp(any());
assertThat(mManagerService.getState()).isEqualTo(STATE_BLE_TURNING_ON);
@@ -349,30 +389,30 @@ public class BluetoothManagerServiceTest {
// trigger the stateChangeCallback from native
btCallback.onBluetoothStateChange(STATE_BLE_TURNING_ON, STATE_BLE_ON);
syncHandler(MESSAGE_BLUETOOTH_STATE_CHANGE);
+ verifyBleStateIntentSent(STATE_BLE_TURNING_ON, STATE_BLE_ON);
return btCallback;
}
private IBluetoothCallback transition_offToOn() throws Exception {
IBluetoothCallback btCallback = transition_offToBleOn();
- verify(mAdapterBinder).bleOnToOn(any());
+ mInOrder.verify(mAdapterBinder).bleOnToOn(any());
// AdapterService go to turning_on and start all profile on its own
btCallback.onBluetoothStateChange(STATE_BLE_ON, STATE_TURNING_ON);
syncHandler(MESSAGE_BLUETOOTH_STATE_CHANGE);
+ verifyBleStateIntentSent(STATE_BLE_ON, STATE_TURNING_ON);
+ verifyStateIntentSent(STATE_OFF, STATE_TURNING_ON);
// When all the profile are started, adapterService consider it is ON
btCallback.onBluetoothStateChange(STATE_TURNING_ON, STATE_ON);
syncHandler(MESSAGE_BLUETOOTH_STATE_CHANGE);
-
- // Check that we sent 6 intent, 4 for BLE: BLE_TURNING_ON + BLE_ON + TURNING_ON + ON
- // and 2 for classic: TURNING_ON + ON
- // TODO(b/280518177): assert the intent are the correct one
- verify(mContext, times(6)).sendBroadcastAsUser(any(), any(), any(), any());
+ verifyBleStateIntentSent(STATE_TURNING_ON, STATE_ON);
+ verifyStateIntentSent(STATE_TURNING_ON, STATE_ON);
return btCallback;
}
private void transition_onToBleOn(IBluetoothCallback btCallback) throws Exception {
- verify(mAdapterBinder).onToBleOn(any());
+ mInOrder.verify(mAdapterBinder).onToBleOn(any());
btCallback.onBluetoothStateChange(STATE_TURNING_OFF, STATE_BLE_ON);
syncHandler(MESSAGE_BLUETOOTH_STATE_CHANGE);
@@ -380,7 +420,7 @@ public class BluetoothManagerServiceTest {
private void transition_onToOff(IBluetoothCallback btCallback) throws Exception {
transition_onToBleOn(btCallback);
- verify(mAdapterBinder).bleOnToOff(any());
+ mInOrder.verify(mAdapterBinder).bleOnToOff(any());
// When all the profile are started, adapterService consider it is ON
btCallback.onBluetoothStateChange(STATE_BLE_TURNING_OFF, STATE_OFF);
@@ -390,62 +430,70 @@ public class BluetoothManagerServiceTest {
@Test
public void enable_whileTurningToBleOn_shouldEnable() throws Exception {
mManagerService.enableBle("enable_whileTurningToBleOn_shouldEnable", mBinder);
- syncHandler(MESSAGE_ENABLE);
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ syncHandler(MESSAGE_ENABLE);
+ }
acceptBluetoothBinding();
- IBluetoothCallback btCallback = captureBluetoothCallback(mAdapterBinder);
+ IBluetoothCallback btCallback = captureBluetoothCallback();
assertThat(mManagerService.getState()).isEqualTo(STATE_BLE_TURNING_ON);
// receive enable when Bluetooth is in BLE_TURNING_ON
mManagerService.enable("enable_whileTurningToBleOn_shouldEnable");
- syncHandler(MESSAGE_ENABLE);
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ syncHandler(MESSAGE_ENABLE);
+ }
btCallback.onBluetoothStateChange(STATE_BLE_TURNING_ON, STATE_BLE_ON);
syncHandler(MESSAGE_BLUETOOTH_STATE_CHANGE);
- verify(mAdapterBinder).bleOnToOn(any());
+ mInOrder.verify(mAdapterBinder).bleOnToOn(any());
}
@Test
public void enable_whileNotYetBoundToBle_shouldEnable() throws Exception {
mManagerService.enableBle("enable_whileTurningToBleOn_shouldEnable", mBinder);
- syncHandler(MESSAGE_ENABLE);
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ syncHandler(MESSAGE_ENABLE);
+ }
assertThat(mManagerService.getState()).isEqualTo(STATE_OFF);
// receive enable when Bluetooth is OFF and not yet binded
mManagerService.enable("enable_whileTurningToBleOn_shouldEnable");
- syncHandler(MESSAGE_ENABLE);
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ syncHandler(MESSAGE_ENABLE);
+ }
acceptBluetoothBinding();
- IBluetoothCallback btCallback = captureBluetoothCallback(mAdapterBinder);
+ IBluetoothCallback btCallback = captureBluetoothCallback();
assertThat(mManagerService.getState()).isEqualTo(STATE_BLE_TURNING_ON);
btCallback.onBluetoothStateChange(STATE_BLE_TURNING_ON, STATE_BLE_ON);
syncHandler(MESSAGE_BLUETOOTH_STATE_CHANGE);
- verify(mAdapterBinder).bleOnToOn(any());
+ mInOrder.verify(mAdapterBinder).bleOnToOn(any());
}
@Test
public void offToBleOn() throws Exception {
mManagerService.enableBle("test_offToBleOn", mBinder);
- syncHandler(MESSAGE_ENABLE);
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ syncHandler(MESSAGE_ENABLE);
+ }
transition_offToBleOn();
- // Check that we sent 2 intent, one for BLE_TURNING_ON, one for BLE_ON
- // TODO(b/280518177): assert the intent are the correct one
- verify(mContext, times(2)).sendBroadcastAsUser(any(), any(), any(), any());
-
// Check that there was no transition to STATE_ON
- verify(mAdapterBinder, times(0)).bleOnToOn(any());
+ mInOrder.verify(mAdapterBinder, never()).bleOnToOn(any());
assertThat(mManagerService.getState()).isEqualTo(STATE_BLE_ON);
}
@Test
public void offToOn() throws Exception {
mManagerService.enable("test_offToOn");
- syncHandler(MESSAGE_ENABLE);
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ syncHandler(MESSAGE_ENABLE);
+ }
transition_offToOn();
@@ -455,13 +503,15 @@ public class BluetoothManagerServiceTest {
@Test
public void crash_whileTransitionState_canRecover() throws Exception {
mManagerService.enableBle("crash_whileTransitionState_canRecover", mBinder);
- syncHandler(MESSAGE_ENABLE);
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ syncHandler(MESSAGE_ENABLE);
+ }
BluetoothManagerService.BluetoothServiceConnection serviceConnection =
acceptBluetoothBinding();
- IBluetoothCallback btCallback = captureBluetoothCallback(mAdapterBinder);
- verify(mAdapterBinder).offToBleOn(anyBoolean(), any());
+ IBluetoothCallback btCallback = captureBluetoothCallback();
+ mInOrder.verify(mAdapterBinder).offToBleOn(anyBoolean(), any());
btCallback.onBluetoothStateChange(STATE_OFF, STATE_BLE_TURNING_ON);
syncHandler(MESSAGE_BLUETOOTH_STATE_CHANGE);
assertThat(mManagerService.getState()).isEqualTo(STATE_BLE_TURNING_ON);
@@ -484,42 +534,136 @@ public class BluetoothManagerServiceTest {
@Test
public void disableAirplane_whenNothing_startBluetooth() throws Exception {
- doReturn(BluetoothManagerService.BLUETOOTH_ON_BLUETOOTH)
- .when(mBluetoothServerProxy)
- .getBluetoothPersistedState(any(), anyInt());
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ mPersistedState = BluetoothManagerService.BLUETOOTH_ON_BLUETOOTH;
+ }
mManagerService.enable("disableAirplane_whenNothing_startBluetooth");
- discardMessage(MESSAGE_ENABLE);
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ discardMessage(MESSAGE_ENABLE);
+ } else {
+ transition_offToOn();
+ }
+
+ assertThat(mLooper.nextMessage()).isNull();
mManagerService.onAirplaneModeChanged(false);
- discardMessage(MESSAGE_ENABLE);
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ discardMessage(MESSAGE_ENABLE);
+ }
}
@Test
- public void disableAirplane_whenFactoryReset_doesNotStartBluetooth() throws Exception {
- doAnswer(
- invocation -> {
- IBinder.DeathRecipient recipient = invocation.getArgument(0);
- recipient.binderDied();
- return null;
- })
- .when(mBinder)
- .linkToDeath(any(), anyInt());
+ @EnableFlags(Flags.FLAG_SYSTEM_SERVER_REMOVE_EXTRA_THREAD_JUMP)
+ public void disable_whenBinding_bluetoothShouldStop_new() throws Exception {
+ mManagerService.enable("disable_whenBinding_bluetoothShouldStop_new");
+ mInOrder.verify(mContext).bindServiceAsUser(any(), any(), anyInt(), any());
+ mManagerService.disable("disable_whenBinding_bluetoothShouldStop_new", true);
+ mInOrder.verify(mContext).unbindService(any());
+ assertThat(mManagerService.getState()).isEqualTo(STATE_OFF);
+ }
- mManagerService.enable("test_offToOn");
+ @Test
+ @EnableFlags(Flags.FLAG_SYSTEM_SERVER_REMOVE_EXTRA_THREAD_JUMP)
+ public void disable_whenTurningBleOn_bluetoothShouldStop() throws Exception {
+ mManagerService.enable("disable_whenBinding_bluetoothShouldStop_new");
+ acceptBluetoothBinding();
+ assertThat(mManagerService.getState()).isEqualTo(STATE_BLE_TURNING_ON);
+ mManagerService.disable("disable_whenBinding_bluetoothShouldStop_new", true);
+ mInOrder.verify(mContext).unbindService(any());
+ assertThat(mManagerService.getState()).isEqualTo(STATE_OFF);
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_SYSTEM_SERVER_REMOVE_EXTRA_THREAD_JUMP)
+ public void disable_whenBinding_bluetoothShouldStop_old() throws Exception {
+ mManagerService.enable("disable_whenBinding_bluetoothShouldStop_old");
syncHandler(MESSAGE_ENABLE);
+ mManagerService.disable("disable_whenBinding_bluetoothShouldStop_old", true);
+ syncHandler(MESSAGE_DISABLE);
+
+ IBluetoothCallback btCallback = transition_offToBleOn();
+ assertThat(mManagerService.getState()).isEqualTo(STATE_BLE_TURNING_OFF);
+
+ btCallback.onBluetoothStateChange(STATE_BLE_TURNING_OFF, STATE_OFF);
+ syncHandler(MESSAGE_BLUETOOTH_STATE_CHANGE);
+
+ mLooper.moveTimeForward(BluetoothManagerService.ENABLE_DISABLE_DELAY_MS);
+ syncHandler(MESSAGE_DISABLE);
+
+ assertThat(mManagerService.getState()).isEqualTo(STATE_OFF);
+ }
+
+ @Test
+ public void disableAirplane_whenFactoryReset_doesNotStartBluetooth() throws Exception {
+ mManagerService.enable("disableAirplane_whenFactoryReset_doesNotStartBluetooth");
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ syncHandler(MESSAGE_ENABLE);
+ }
IBluetoothCallback btCallback = transition_offToOn();
assertThat(mManagerService.getState()).isEqualTo(STATE_ON);
mManagerService.mHandler.sendEmptyMessage(MESSAGE_RESTORE_USER_SETTING_OFF);
syncHandler(MESSAGE_RESTORE_USER_SETTING_OFF);
- syncHandler(MESSAGE_DISABLE);
- mLooper.moveTimeForward(BluetoothManagerService.ENABLE_DISABLE_DELAY_MS);
- syncHandler(MESSAGE_HANDLE_DISABLE_DELAYED);
- mLooper.moveTimeForward(BluetoothManagerService.ENABLE_DISABLE_DELAY_MS);
- syncHandler(MESSAGE_HANDLE_DISABLE_DELAYED);
+ if (!Flags.systemServerRemoveExtraThreadJump()) {
+ syncHandler(MESSAGE_DISABLE);
+ mLooper.moveTimeForward(BluetoothManagerService.ENABLE_DISABLE_DELAY_MS);
+ syncHandler(MESSAGE_HANDLE_DISABLE_DELAYED);
+ mLooper.moveTimeForward(BluetoothManagerService.ENABLE_DISABLE_DELAY_MS);
+ syncHandler(MESSAGE_HANDLE_DISABLE_DELAYED);
+ }
transition_onToOff(btCallback);
mManagerService.onAirplaneModeChanged(false);
assertThat(mLooper.nextMessage()).isNull(); // Must not create a MESSAGE_ENABLE
}
+
+ @Test
+ @EnableFlags({
+ Flags.FLAG_SYSTEM_SERVER_REMOVE_EXTRA_THREAD_JUMP,
+ Flags.FLAG_ENABLE_BLE_WHILE_DISABLING_AIRPLANE
+ })
+ public void enableBle_whenDisableAirplaneIsDelayed_startBluetooth() throws Exception {
+ mManagerService.enable("enableBle_whenDisableAirplaneIsDelayed_startBluetooth");
+ IBluetoothCallback btCallback = transition_offToOn();
+ mManagerService.onAirplaneModeChanged(true);
+ assertThat(mManagerService.getState()).isEqualTo(STATE_TURNING_OFF);
+
+ // Generate an event that will be delayed due to the TURNING_OFF state
+ mManagerService.onAirplaneModeChanged(false);
+
+ transition_onToBleOn(btCallback);
+ mInOrder.verify(mAdapterBinder).bleOnToOff(any());
+ assertThat(mManagerService.getState()).isEqualTo(STATE_BLE_TURNING_OFF);
+
+ // As soon as we left BLE_ON, generate a call from 3p app that request to turn on Bluetooth
+ mManagerService.enableBle("enableBle_whenDisableAirplaneIsDelayed_startBluetooth", mBinder);
+
+ // When all the profile are started, adapterService consider it is ON
+ btCallback.onBluetoothStateChange(STATE_BLE_TURNING_OFF, STATE_OFF);
+ syncHandler(MESSAGE_BLUETOOTH_STATE_CHANGE);
+
+ transition_offToOn();
+ assertThat(mManagerService.getState()).isEqualTo(STATE_ON);
+ }
+
+ @SafeVarargs
+ private void verifyIntentSent(Matcher<Intent>... matchers) {
+ mInOrder.verify(mContext)
+ .sendBroadcastAsUser(
+ MockitoHamcrest.argThat(AllOf.allOf(matchers)), any(), any(), any());
+ }
+
+ private void verifyBleStateIntentSent(int from, int to) {
+ verifyIntentSent(
+ hasAction(BluetoothAdapter.ACTION_BLE_STATE_CHANGED),
+ hasExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, from),
+ hasExtra(BluetoothAdapter.EXTRA_STATE, to));
+ }
+
+ private void verifyStateIntentSent(int from, int to) {
+ verifyIntentSent(
+ hasAction(BluetoothAdapter.ACTION_STATE_CHANGED),
+ hasExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, from),
+ hasExtra(BluetoothAdapter.EXTRA_STATE, to));
+ }
}
diff --git a/sysprop/OWNERS b/sysprop/OWNERS
deleted file mode 100644
index 5b3f4bad26..0000000000
--- a/sysprop/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-wescande@google.com
diff --git a/system/BUILD.gn b/system/BUILD.gn
index b86ca5f392..1d6325e6d9 100644
--- a/system/BUILD.gn
+++ b/system/BUILD.gn
@@ -41,7 +41,6 @@ group("bluetooth") {
#if (use.test) {
#group("bluetooth_tests") {
#deps = [
- #"//bt/system/btcore:net_test_btcore",
#"//bt/system/common:bluetooth_test_common",
#"//bt/system/profile/avrcp:net_test_avrcp",
#"//bt/system/service:bluetoothtbd_test",
@@ -76,7 +75,6 @@ config("target_defaults") {
"//bt/system",
"//bt/flags/exported_include",
"//bt/sysprop/exported_include",
- "//bt/system/linux_include",
"//bt/system/include",
"//bt/system/gd",
"//bt/system/pdl/hci/include",
diff --git a/system/OWNERS b/system/OWNERS
deleted file mode 100644
index b2acb91716..0000000000
--- a/system/OWNERS
+++ /dev/null
@@ -1,18 +0,0 @@
-# Reviewers for /system
-
-bhaktha@google.com
-eruffieux@google.com
-hallstrom@google.com
-henrichataing@google.com
-jpawlowski@google.com
-okamil@google.com
-poahlo@google.com
-rongxuan@google.com
-rwt@google.com
-wescande@google.com
-
-# Reviewers for Channel Sounding related files
-per-file /bta/ras/*=file:/OWNERS_channel_sounding
-per-file /gd/hal/ranging_hal*=file:/OWNERS_channel_sounding
-per-file /gd/hci/distance_measurement_*=file:/OWNERS_channel_sounding
-per-file /main/shim/distance_measurement_manager*=file:/OWNERS_channel_sounding
diff --git a/system/audio_hal_interface/aidl/le_audio_software_aidl.cc b/system/audio_hal_interface/aidl/le_audio_software_aidl.cc
index be7cf3a6b2..e0b96475d3 100644
--- a/system/audio_hal_interface/aidl/le_audio_software_aidl.cc
+++ b/system/audio_hal_interface/aidl/le_audio_software_aidl.cc
@@ -30,6 +30,7 @@
#include "common/strings.h"
#include "hal_version_manager.h"
#include "le_audio_utils.h"
+#include "osi/include/properties.h"
namespace bluetooth {
namespace audio {
@@ -694,6 +695,14 @@ bluetooth::audio::le_audio::OffloadCapabilities get_offload_capabilities() {
return {offload_capabilities, broadcast_offload_capabilities};
}
+static bool IsUsingCodecExtensibility() {
+ auto codec_ext_status =
+ osi_property_get_bool("bluetooth.core.le_audio.codec_extension_aidl.enabled", false);
+
+ log::debug("Using codec extensibility AIDL: {}", codec_ext_status);
+ return codec_ext_status;
+}
+
AudioConfiguration stream_config_to_hal_audio_config(
const ::bluetooth::le_audio::stream_config& offload_config) {
LeAudioConfiguration ucast_config = {
@@ -726,6 +735,7 @@ AudioConfiguration stream_config_to_hal_audio_config(
.blocksPerSdu = static_cast<int8_t>(offload_config.codec_frames_blocks_per_sdu),
};
ucast_config.leAudioCodecConfig = LeAudioCodecConfiguration(lc3_config);
+ ucast_config.codecType = CodecType::LC3;
lc3_codec_config_found = true;
}
@@ -741,14 +751,20 @@ AudioConfiguration stream_config_to_hal_audio_config(
BLE_ADDRESS_RANDOM;
}
- ucast_config.streamMap.push_back({
+ LeAudioConfiguration::StreamMap map_entry = {
.streamHandle = info.stream_handle,
.audioChannelAllocation = static_cast<int32_t>(info.audio_channel_allocation),
.isStreamActive = info.is_stream_active,
- .aseConfiguration = GetAidlLeAudioAseConfigurationFromStackFormat(
- info.codec_config, info.target_latency, info.target_phy, info.metadata),
- .bluetoothDeviceAddress = aidl_device_address,
- });
+ };
+
+ // Add the additional codec extensibility data fields
+ if (IsUsingCodecExtensibility()) {
+ map_entry.aseConfiguration = GetAidlLeAudioAseConfigurationFromStackFormat(
+ info.codec_config, info.target_latency, info.target_phy, info.metadata);
+ map_entry.bluetoothDeviceAddress = aidl_device_address;
+ }
+
+ ucast_config.streamMap.push_back(map_entry);
}
if (!lc3_codec_config_found) {
diff --git a/system/bta/Android.bp b/system/bta/Android.bp
index 52d34d59cc..22074caf65 100644
--- a/system/bta/Android.bp
+++ b/system/bta/Android.bp
@@ -231,6 +231,7 @@ cc_test {
":TestMockBtif",
":TestMockDevice",
":TestMockMainShim",
+ ":TestMockMainShim",
":TestMockMainShimEntry",
":TestMockStackA2dp",
":TestMockStackAcl",
@@ -243,7 +244,6 @@ cc_test {
":TestMockStackGatt",
":TestMockStackHid",
":TestMockStackL2cap",
- ":TestMockStackMetrics",
":TestMockStackPan",
":TestMockStackRfcomm",
":TestMockStackRnr",
@@ -339,10 +339,10 @@ cc_test {
":TestMockBtif",
":TestMockDevice",
":TestMockMainShim",
+ ":TestMockMainShim",
":TestMockMainShimEntry",
":TestMockStackBtm",
":TestMockStackL2cap",
- ":TestMockStackMetrics",
"test/gatt/database_builder_sample_device_test.cc",
"test/gatt/database_builder_test.cc",
"test/gatt/database_test.cc",
@@ -1347,6 +1347,74 @@ cc_test {
}
cc_test {
+ name: "bluetooth_hearing_aid_test",
+ test_suites: ["general-tests"],
+ defaults: [
+ "fluoride_bta_defaults",
+ "mts_defaults",
+ ],
+ host_supported: true,
+ include_dirs: [
+ "packages/modules/Bluetooth/system",
+ "packages/modules/Bluetooth/system/bta/include",
+ "packages/modules/Bluetooth/system/bta/test/common",
+ "packages/modules/Bluetooth/system/stack/include",
+ ],
+ srcs: [
+ ":TestCommonMockFunctions",
+ ":TestMockBtaHearingAidAudioSource",
+ ":TestMockDevice",
+ ":TestMockMainShim",
+ ":TestMockMainShimEntry",
+ ":TestMockStackBtmInterface",
+ ":TestMockStackBtmIso",
+ ":TestMockStackGapConnInterface",
+ ":TestMockStackL2cap",
+ ":TestStubOsi",
+ "gatt/database.cc",
+ "gatt/database_builder.cc",
+ "hearing_aid/hearing_aid.cc",
+ "hearing_aid/hearing_aid_test.cc",
+ "test/common/bta_gatt_api_mock.cc",
+ "test/common/bta_gatt_queue_mock.cc",
+ "test/common/btif_storage_mock.cc",
+ "test/common/btm_api_mock.cc",
+ ],
+ shared_libs: [
+ "libbase",
+ "libcrypto",
+ "liblog",
+ ],
+ static_libs: [
+ "bluetooth_flags_c_lib_for_test",
+ "libaconfig_storage_read_api_cc",
+ "libbluetooth-types",
+ "libbluetooth_crypto_toolbox",
+ "libbluetooth_gd",
+ "libbluetooth_log",
+ "libbt-audio-asrc",
+ "libbt-btu-main-thread",
+ "libbt-common",
+ "libbt-platform-protos-lite",
+ "libchrome",
+ "libevent",
+ "libg722codec",
+ "libgmock",
+ "server_configurable_flags",
+ ],
+ sanitize: {
+ cfi: true,
+ scs: true,
+ address: true,
+ all_undefined: true,
+ integer_overflow: true,
+ diag: {
+ undefined: true,
+ },
+ },
+}
+
+cc_test {
name: "bluetooth_hh_test",
test_suites: ["general-tests"],
defaults: [
diff --git a/system/bta/BUILD.gn b/system/bta/BUILD.gn
index 9c28016617..f621539151 100644
--- a/system/bta/BUILD.gn
+++ b/system/bta/BUILD.gn
@@ -143,7 +143,6 @@ static_library("bta") {
"sys",
"//bt/system/",
"//bt/system/include",
- "//bt/system/linux_include",
"//bt/system/bta",
"//bt/system/bta/aics/include",
"//bt/system/gd",
diff --git a/system/bta/dm/bta_dm_act.cc b/system/bta/dm/bta_dm_act.cc
index 48e0f16c99..ddc481171f 100644
--- a/system/bta/dm/bta_dm_act.cc
+++ b/system/bta/dm/bta_dm_act.cc
@@ -545,7 +545,7 @@ void bta_dm_remove_device(const RawAddress& target) {
if (le_connected || bredr_connected) {
// Wait for all transports to be disconnected
- tBTA_DM_REMOVE_PENDNIG node = {pseudo_addr, identity_addr, le_connected, bredr_connected};
+ tBTA_DM_REMOVE_PENDING node = {pseudo_addr, identity_addr, le_connected, bredr_connected};
bta_dm_cb.pending_removals.push_back(node);
log::info(
"Waiting for disconnection over LE:{}, BR/EDR:{} for pseudo address: {}, identity "
diff --git a/system/bta/dm/bta_dm_disc.cc b/system/bta/dm/bta_dm_disc.cc
index b3f010e86e..79d3421361 100644
--- a/system/bta/dm/bta_dm_disc.cc
+++ b/system/bta/dm/bta_dm_disc.cc
@@ -152,8 +152,7 @@ gatt_interface_t& get_gatt_interface() { return *gatt_interface; }
void bta_dm_disc_gatt_cancel_open(const RawAddress& bd_addr) {
get_gatt_interface().BTA_GATTC_CancelOpen(0, bd_addr, false);
- if (com::android::bluetooth::flags::cancel_open_discovery_client() &&
- bta_dm_discovery_cb.client_if != BTA_GATTS_INVALID_IF) {
+ if (bta_dm_discovery_cb.client_if != BTA_GATTS_INVALID_IF) {
get_gatt_interface().BTA_GATTC_CancelOpen(bta_dm_discovery_cb.client_if, bd_addr, true);
}
}
@@ -559,11 +558,7 @@ static void bta_dm_gatt_disc_complete(tCONN_ID conn_id, tGATT_STATUS status) {
} else {
log::info("Discovery complete for invalid conn ID. Will pick up next job");
- if (com::android::bluetooth::flags::cancel_open_discovery_client()) {
- bta_dm_close_gatt_conn(bta_dm_discovery_cb.conn_id);
- } else {
- bta_dm_discovery_cb.conn_id = GATT_INVALID_CONN_ID;
- }
+ bta_dm_close_gatt_conn(bta_dm_discovery_cb.conn_id);
if (bta_dm_discovery_cb.transports & BT_TRANSPORT_BR_EDR) {
log::info("classic discovery still pending {}", bta_dm_discovery_cb.peer_bdaddr);
return;
diff --git a/system/bta/dm/bta_dm_int.h b/system/bta/dm/bta_dm_int.h
index 521a8072de..26f7e4d97c 100644
--- a/system/bta/dm/bta_dm_int.h
+++ b/system/bta/dm/bta_dm_int.h
@@ -81,7 +81,7 @@ inline std::string device_info_text(tBTA_DM_DEV_INFO info) {
#define BTA_DM_PM_EXECUTE 3
typedef uint8_t tBTA_DM_PM_REQ;
-struct tBTA_DM_REMOVE_PENDNIG {
+struct tBTA_DM_REMOVE_PENDING {
RawAddress pseudo_addr;
RawAddress identity_addr;
bool le_connected;
@@ -215,7 +215,7 @@ typedef struct {
#endif
alarm_t* switch_delay_timer;
- std::list<tBTA_DM_REMOVE_PENDNIG> pending_removals;
+ std::list<tBTA_DM_REMOVE_PENDING> pending_removals;
} tBTA_DM_CB;
/* DI control block */
diff --git a/system/bta/gatt/bta_gattc_act.cc b/system/bta/gatt/bta_gattc_act.cc
index 3b6069b1a1..346d7c3d6a 100644
--- a/system/bta/gatt/bta_gattc_act.cc
+++ b/system/bta/gatt/bta_gattc_act.cc
@@ -132,28 +132,17 @@ void bta_gattc_disable() {
return;
}
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- if (!bta_gattc_cb.cl_rcb_map.empty()) {
- bta_gattc_cb.state = BTA_GATTC_STATE_DISABLING;
- }
-
- // An entry can be erased during deregister, use a copied collection
- std::vector<tGATT_IF> gatt_ifs;
- for (auto& [gatt_if, p_rcb] : bta_gattc_cb.cl_rcb_map) {
- gatt_ifs.push_back(gatt_if);
- }
- for (auto& gatt_if : gatt_ifs) {
- bta_gattc_deregister(bta_gattc_cb.cl_rcb_map[gatt_if].get());
- }
- } else {
- for (i = 0; i < BTA_GATTC_CL_MAX; i++) {
- if (!bta_gattc_cb.cl_rcb[i].in_use) {
- continue;
- }
+ if (!bta_gattc_cb.cl_rcb_map.empty()) {
+ bta_gattc_cb.state = BTA_GATTC_STATE_DISABLING;
+ }
- bta_gattc_cb.state = BTA_GATTC_STATE_DISABLING;
- bta_gattc_deregister(&bta_gattc_cb.cl_rcb[i]);
- }
+ // An entry can be erased during deregister, use a copied collection
+ std::vector<tGATT_IF> gatt_ifs;
+ for (auto& [gatt_if, p_rcb] : bta_gattc_cb.cl_rcb_map) {
+ gatt_ifs.push_back(gatt_if);
+ }
+ for (auto& gatt_if : gatt_ifs) {
+ bta_gattc_deregister(bta_gattc_cb.cl_rcb_map[gatt_if].get());
}
/* no registered apps, indicate disable completed */
@@ -187,55 +176,25 @@ void bta_gattc_register(const Uuid& app_uuid, const std::string& name, tBTA_GATT
bta_gattc_enable();
}
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- client_if = GATT_Register(app_uuid, name, &bta_gattc_cl_cback, eatt_support);
- if (client_if == 0) {
- log::error("Register with GATT stack failed");
- status = GATT_ERROR;
- } else {
- auto p_rcb = std::make_unique<tBTA_GATTC_RCB>();
- p_rcb->in_use = true;
- p_rcb->p_cback = p_cback;
- p_rcb->app_uuid = app_uuid;
- p_rcb->client_if = client_if;
- bta_gattc_cb.cl_rcb_map.emplace(client_if, std::move(p_rcb));
-
- log::debug(
- "Registered GATT client interface {} with uuid={}, starting it on "
- "main thread",
- client_if, app_uuid.ToString());
-
- do_in_main_thread(base::BindOnce(&bta_gattc_start_if, client_if));
- status = GATT_SUCCESS;
- }
+ client_if = GATT_Register(app_uuid, name, &bta_gattc_cl_cback, eatt_support);
+ if (client_if == 0) {
+ log::error("Register with GATT stack failed");
+ status = GATT_ERROR;
} else {
- for (uint8_t i = 0; i < BTA_GATTC_CL_MAX; i++) {
- if (!bta_gattc_cb.cl_rcb[i].in_use) {
- bta_gattc_cb.cl_rcb[i].client_if =
- GATT_Register(app_uuid, "GattClient", &bta_gattc_cl_cback, eatt_support);
- if (bta_gattc_cb.cl_rcb[i].client_if == 0) {
- log::error("Register with GATT stack failed with index {}, trying next index", i);
- status = GATT_ERROR;
- } else {
- bta_gattc_cb.cl_rcb[i].in_use = true;
- bta_gattc_cb.cl_rcb[i].p_cback = p_cback;
- bta_gattc_cb.cl_rcb[i].app_uuid = app_uuid;
-
- /* BTA use the same client interface as BTE GATT statck */
- client_if = bta_gattc_cb.cl_rcb[i].client_if;
-
- log::debug(
- "Registered GATT client interface {} with uuid={}, starting it on "
- "main thread",
- client_if, app_uuid.ToString());
-
- do_in_main_thread(base::BindOnce(&bta_gattc_start_if, client_if));
-
- status = GATT_SUCCESS;
- break;
- }
- }
- }
+ auto p_rcb = std::make_unique<tBTA_GATTC_RCB>();
+ p_rcb->in_use = true;
+ p_rcb->p_cback = p_cback;
+ p_rcb->app_uuid = app_uuid;
+ p_rcb->client_if = client_if;
+ bta_gattc_cb.cl_rcb_map.emplace(client_if, std::move(p_rcb));
+
+ log::debug(
+ "Registered GATT client interface {} with uuid={}, starting it on "
+ "main thread",
+ client_if, app_uuid.ToString());
+
+ do_in_main_thread(base::BindOnce(&bta_gattc_start_if, client_if));
+ status = GATT_SUCCESS;
}
if (!cb.is_null()) {
@@ -258,26 +217,13 @@ void bta_gattc_deregister(tBTA_GATTC_RCB* p_clreg) {
continue;
}
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- if (bta_gattc_cb.bg_track[i].cif_set.contains(p_clreg->client_if)) {
- bta_gattc_mark_bg_conn(p_clreg->client_if, bta_gattc_cb.bg_track[i].remote_bda, false);
- if (!GATT_CancelConnect(p_clreg->client_if, bta_gattc_cb.bg_track[i].remote_bda, false)) {
- log::warn(
- "Unable to cancel GATT connection client_if:{} peer:{} "
- "is_direct:{}",
- p_clreg->client_if, bta_gattc_cb.bg_track[i].remote_bda, false);
- }
- }
- } else {
- if (bta_gattc_cb.bg_track[i].cif_mask &
- ((tBTA_GATTC_CIF_MASK)1 << (p_clreg->client_if - 1))) {
- bta_gattc_mark_bg_conn(p_clreg->client_if, bta_gattc_cb.bg_track[i].remote_bda, false);
- if (!GATT_CancelConnect(p_clreg->client_if, bta_gattc_cb.bg_track[i].remote_bda, false)) {
- log::warn(
- "Unable to cancel GATT connection client_if:{} peer:{} "
- "is_direct:{}",
- p_clreg->client_if, bta_gattc_cb.bg_track[i].remote_bda, false);
- }
+ if (bta_gattc_cb.bg_track[i].cif_set.contains(p_clreg->client_if)) {
+ bta_gattc_mark_bg_conn(p_clreg->client_if, bta_gattc_cb.bg_track[i].remote_bda, false);
+ if (!GATT_CancelConnect(p_clreg->client_if, bta_gattc_cb.bg_track[i].remote_bda, false)) {
+ log::warn(
+ "Unable to cancel GATT connection client_if:{} peer:{} "
+ "is_direct:{}",
+ p_clreg->client_if, bta_gattc_cb.bg_track[i].remote_bda, false);
}
}
}
@@ -288,38 +234,23 @@ void bta_gattc_deregister(tBTA_GATTC_RCB* p_clreg) {
}
/* close all CLCB related to this app */
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& p_clcb : bta_gattc_cb.clcb_set) {
- if (!p_clcb->in_use || p_clcb->p_rcb != p_clreg) {
- continue;
- }
- p_clreg->dereg_pending = true;
-
- tBTA_GATTC_DATA gattc_data = {
- .hdr =
- {
- .event = BTA_GATTC_API_CLOSE_EVT,
- .layer_specific = static_cast<uint16_t>(p_clcb->bta_conn_id),
- },
- };
- bta_gattc_close(p_clcb.get(), &gattc_data);
- }
- // deallocated clcbs will not be accessed. Let them be claened up.
- bta_gattc_cleanup_clcb();
- } else {
- for (size_t i = 0; i < BTA_GATTC_CLCB_MAX; i++) {
- if (!bta_gattc_cb.clcb[i].in_use || (bta_gattc_cb.clcb[i].p_rcb != p_clreg)) {
- continue;
- }
-
- p_clreg->dereg_pending = true;
-
- BT_HDR_RIGID buf;
- buf.event = BTA_GATTC_API_CLOSE_EVT;
- buf.layer_specific = static_cast<uint16_t>(bta_gattc_cb.clcb[i].bta_conn_id);
- bta_gattc_close(&bta_gattc_cb.clcb[i], (tBTA_GATTC_DATA*)&buf);
+ for (auto& p_clcb : bta_gattc_cb.clcb_set) {
+ if (!p_clcb->in_use || p_clcb->p_rcb != p_clreg) {
+ continue;
}
+ p_clreg->dereg_pending = true;
+
+ tBTA_GATTC_DATA gattc_data = {
+ .hdr =
+ {
+ .event = BTA_GATTC_API_CLOSE_EVT,
+ .layer_specific = static_cast<uint16_t>(p_clcb->bta_conn_id),
+ },
+ };
+ bta_gattc_close(p_clcb.get(), &gattc_data);
}
+ // deallocated clcbs will not be accessed. Let them be claened up.
+ bta_gattc_cleanup_clcb();
}
/** process connect API request */
@@ -736,21 +667,12 @@ void bta_gattc_close(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) {
/** when a SRCB finished discovery, tell all related clcb */
void bta_gattc_reset_discover_st(tBTA_GATTC_SERV* p_srcb, tGATT_STATUS status) {
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& p_clcb : bta_gattc_cb.clcb_set) {
- if (p_clcb->p_srcb != p_srcb) {
- continue;
- }
- p_clcb->status = status;
- bta_gattc_sm_execute(p_clcb.get(), BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
- }
- } else {
- for (size_t i = 0; i < BTA_GATTC_CLCB_MAX; i++) {
- if (bta_gattc_cb.clcb[i].p_srcb == p_srcb) {
- bta_gattc_cb.clcb[i].status = status;
- bta_gattc_sm_execute(&bta_gattc_cb.clcb[i], BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
- }
+ for (auto& p_clcb : bta_gattc_cb.clcb_set) {
+ if (p_clcb->p_srcb != p_srcb) {
+ continue;
}
+ p_clcb->status = status;
+ bta_gattc_sm_execute(p_clcb.get(), BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
}
}
@@ -777,23 +699,13 @@ void bta_gattc_disc_close(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data
/** when a SRCB start discovery, tell all related clcb and set the state */
static void bta_gattc_set_discover_st(tBTA_GATTC_SERV* p_srcb) {
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& p_clcb : bta_gattc_cb.clcb_set) {
- if (p_clcb->p_srcb != p_srcb) {
- continue;
- }
- p_clcb->status = GATT_SUCCESS;
- p_clcb->state = BTA_GATTC_DISCOVER_ST;
- p_clcb->request_during_discovery = BTA_GATTC_DISCOVER_REQ_NONE;
- }
- } else {
- for (size_t i = 0; i < BTA_GATTC_CLCB_MAX; i++) {
- if (bta_gattc_cb.clcb[i].p_srcb == p_srcb) {
- bta_gattc_cb.clcb[i].status = GATT_SUCCESS;
- bta_gattc_cb.clcb[i].state = BTA_GATTC_DISCOVER_ST;
- bta_gattc_cb.clcb[i].request_during_discovery = BTA_GATTC_DISCOVER_REQ_NONE;
- }
+ for (auto& p_clcb : bta_gattc_cb.clcb_set) {
+ if (p_clcb->p_srcb != p_srcb) {
+ continue;
}
+ p_clcb->status = GATT_SUCCESS;
+ p_clcb->state = BTA_GATTC_DISCOVER_ST;
+ p_clcb->request_during_discovery = BTA_GATTC_DISCOVER_REQ_NONE;
}
}
@@ -1422,12 +1334,8 @@ static void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB* p_clreg) {
memset(&cb_data, 0, sizeof(tBTA_GATTC));
GATT_Deregister(p_clreg->client_if);
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- if (bta_gattc_cb.cl_rcb_map.erase(p_clreg->client_if) == 0) {
- log::warn("deregistered unknown rcb client_if={}", p_clreg->client_if);
- }
- } else {
- memset(p_clreg, 0, sizeof(tBTA_GATTC_RCB));
+ if (bta_gattc_cb.cl_rcb_map.erase(p_clreg->client_if) == 0) {
+ log::warn("deregistered unknown rcb client_if={}", p_clreg->client_if);
}
cb_data.reg_oper.client_if = client_if;
@@ -1490,20 +1398,11 @@ void bta_gattc_process_api_refresh(const RawAddress& remote_bda) {
if (p_srvc_cb->connected && p_srvc_cb->num_clcb != 0) {
bool found = false;
tBTA_GATTC_CLCB* p_clcb = &bta_gattc_cb.clcb[0];
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& p_clcb_i : bta_gattc_cb.clcb_set) {
- if (p_clcb_i->in_use && p_clcb_i->p_srcb == p_srvc_cb) {
- p_clcb = p_clcb_i.get();
- found = true;
- break;
- }
- }
- } else {
- for (size_t i = 0; i < BTA_GATTC_CLCB_MAX; i++, p_clcb++) {
- if (p_clcb->in_use && p_clcb->p_srcb == p_srvc_cb) {
- found = true;
- break;
- }
+ for (auto& p_clcb_i : bta_gattc_cb.clcb_set) {
+ if (p_clcb_i->in_use && p_clcb_i->p_srcb == p_srvc_cb) {
+ p_clcb = p_clcb_i.get();
+ found = true;
+ break;
}
}
if (found) {
@@ -1563,38 +1462,19 @@ static bool bta_gattc_process_srvc_chg_ind(tCONN_ID conn_id, tBTA_GATTC_RCB* p_c
/* not an opened connection; or connection busy */
/* search for first available clcb and start discovery */
if (p_clcb == NULL || (p_clcb && p_clcb->p_q_cmd != NULL)) {
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& p_clcb_i : bta_gattc_cb.clcb_set) {
- if (p_clcb_i->in_use && p_clcb_i->p_srcb == p_srcb && p_clcb_i->p_q_cmd == NULL) {
- p_clcb = p_clcb_i.get();
- break;
- }
- }
- } else {
- for (size_t i = 0; i < BTA_GATTC_CLCB_MAX; i++) {
- if (bta_gattc_cb.clcb[i].in_use && bta_gattc_cb.clcb[i].p_srcb == p_srcb &&
- bta_gattc_cb.clcb[i].p_q_cmd == NULL) {
- p_clcb = &bta_gattc_cb.clcb[i];
- break;
- }
+ for (auto& p_clcb_i : bta_gattc_cb.clcb_set) {
+ if (p_clcb_i->in_use && p_clcb_i->p_srcb == p_srcb && p_clcb_i->p_q_cmd == NULL) {
+ p_clcb = p_clcb_i.get();
+ break;
}
}
}
// Use a busy CLCB to start discovery if no CLCB is available, this will be queued.
if (com::android::bluetooth::flags::start_discover_service_changed() && p_clcb == NULL) {
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& p_clcb_i : bta_gattc_cb.clcb_set) {
- if (p_clcb_i->in_use && p_clcb_i->p_srcb == p_srcb) {
- p_clcb = p_clcb_i.get();
- break;
- }
- }
- } else {
- for (size_t i = 0; i < BTA_GATTC_CLCB_MAX; i++) {
- if (bta_gattc_cb.clcb[i].in_use && bta_gattc_cb.clcb[i].p_srcb == p_srcb) {
- p_clcb = &bta_gattc_cb.clcb[i];
- break;
- }
+ for (auto& p_clcb_i : bta_gattc_cb.clcb_set) {
+ if (p_clcb_i->in_use && p_clcb_i->p_srcb == p_srcb) {
+ p_clcb = p_clcb_i.get();
+ break;
}
}
}
diff --git a/system/bta/gatt/bta_gattc_utils.cc b/system/bta/gatt/bta_gattc_utils.cc
index 23b150b829..523cf90fe5 100644
--- a/system/bta/gatt/bta_gattc_utils.cc
+++ b/system/bta/gatt/bta_gattc_utils.cc
@@ -25,7 +25,6 @@
#define LOG_TAG "bt_bta_gattc"
#include <bluetooth/log.h>
-#include <com_android_bluetooth_flags.h>
#include <cstdint>
@@ -58,23 +57,11 @@ static uint8_t ble_acceptlist_size() {
*
******************************************************************************/
tBTA_GATTC_RCB* bta_gattc_cl_get_regcb(uint8_t client_if) {
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- auto it = bta_gattc_cb.cl_rcb_map.find(client_if);
- if (it == bta_gattc_cb.cl_rcb_map.end()) {
- return NULL;
- } else {
- return it->second.get();
- }
- } else {
- uint8_t i = 0;
- tBTA_GATTC_RCB* p_clrcb = &bta_gattc_cb.cl_rcb[0];
-
- for (i = 0; i < BTA_GATTC_CL_MAX; i++, p_clrcb++) {
- if (p_clrcb->in_use && p_clrcb->client_if == client_if) {
- return p_clrcb;
- }
- }
+ auto it = bta_gattc_cb.cl_rcb_map.find(client_if);
+ if (it == bta_gattc_cb.cl_rcb_map.end()) {
return NULL;
+ } else {
+ return it->second.get();
}
}
/*******************************************************************************
@@ -86,20 +73,7 @@ tBTA_GATTC_RCB* bta_gattc_cl_get_regcb(uint8_t client_if) {
* Returns pointer to the regcb
*
******************************************************************************/
-uint8_t bta_gattc_num_reg_app(void) {
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- return (uint8_t)bta_gattc_cb.cl_rcb_map.size();
- } else {
- uint8_t i = 0, j = 0;
-
- for (i = 0; i < BTA_GATTC_CL_MAX; i++) {
- if (bta_gattc_cb.cl_rcb[i].in_use) {
- j++;
- }
- }
- return j;
- }
-}
+uint8_t bta_gattc_num_reg_app(void) { return (uint8_t)bta_gattc_cb.cl_rcb_map.size(); }
/*******************************************************************************
*
* Function bta_gattc_find_clcb_by_cif
@@ -111,21 +85,10 @@ uint8_t bta_gattc_num_reg_app(void) {
******************************************************************************/
tBTA_GATTC_CLCB* bta_gattc_find_clcb_by_cif(uint8_t client_if, const RawAddress& remote_bda,
tBT_TRANSPORT transport) {
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& p_clcb : bta_gattc_cb.clcb_set) {
- if (p_clcb->in_use && p_clcb->p_rcb->client_if == client_if &&
- p_clcb->transport == transport && p_clcb->bda == remote_bda) {
- return p_clcb.get();
- }
- }
- } else {
- tBTA_GATTC_CLCB* p_clcb = &bta_gattc_cb.clcb[0];
-
- for (size_t i = 0; i < BTA_GATTC_CLCB_MAX; i++, p_clcb++) {
- if (p_clcb->in_use && p_clcb->p_rcb->client_if == client_if &&
- p_clcb->transport == transport && p_clcb->bda == remote_bda) {
- return p_clcb;
- }
+ for (auto& p_clcb : bta_gattc_cb.clcb_set) {
+ if (p_clcb->in_use && p_clcb->p_rcb->client_if == client_if && p_clcb->transport == transport &&
+ p_clcb->bda == remote_bda) {
+ return p_clcb.get();
}
}
return NULL;
@@ -140,19 +103,9 @@ tBTA_GATTC_CLCB* bta_gattc_find_clcb_by_cif(uint8_t client_if, const RawAddress&
*
******************************************************************************/
tBTA_GATTC_CLCB* bta_gattc_find_clcb_by_conn_id(tCONN_ID conn_id) {
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& p_clcb : bta_gattc_cb.clcb_set) {
- if (p_clcb->in_use && p_clcb->bta_conn_id == conn_id) {
- return p_clcb.get();
- }
- }
- } else {
- tBTA_GATTC_CLCB* p_clcb = &bta_gattc_cb.clcb[0];
-
- for (size_t i = 0; i < BTA_GATTC_CLCB_MAX; i++, p_clcb++) {
- if (p_clcb->in_use && p_clcb->bta_conn_id == conn_id) {
- return p_clcb;
- }
+ for (auto& p_clcb : bta_gattc_cb.clcb_set) {
+ if (p_clcb != NULL && p_clcb->in_use && p_clcb->bta_conn_id == conn_id) {
+ return p_clcb.get();
}
}
return NULL;
@@ -171,63 +124,30 @@ tBTA_GATTC_CLCB* bta_gattc_clcb_alloc(tGATT_IF client_if, const RawAddress& remo
tBT_TRANSPORT transport) {
tBTA_GATTC_CLCB* p_clcb = NULL;
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- bta_gattc_cleanup_clcb();
- auto [p_clcb_i, b] = bta_gattc_cb.clcb_set.emplace(std::make_unique<tBTA_GATTC_CLCB>());
- p_clcb = p_clcb_i->get();
+ bta_gattc_cleanup_clcb();
+ auto [p_clcb_i, b] = bta_gattc_cb.clcb_set.emplace(std::make_unique<tBTA_GATTC_CLCB>());
+ p_clcb = p_clcb_i->get();
- p_clcb->in_use = true;
- p_clcb->status = GATT_SUCCESS;
- p_clcb->transport = transport;
- p_clcb->bda = remote_bda;
- p_clcb->p_q_cmd = NULL;
+ p_clcb->in_use = true;
+ p_clcb->status = GATT_SUCCESS;
+ p_clcb->transport = transport;
+ p_clcb->bda = remote_bda;
+ p_clcb->p_q_cmd = NULL;
- p_clcb->p_rcb = bta_gattc_cl_get_regcb(client_if);
+ p_clcb->p_rcb = bta_gattc_cl_get_regcb(client_if);
- p_clcb->p_srcb = bta_gattc_find_srcb(remote_bda);
- if (p_clcb->p_srcb == NULL) {
- p_clcb->p_srcb = bta_gattc_srcb_alloc(remote_bda);
- }
+ p_clcb->p_srcb = bta_gattc_find_srcb(remote_bda);
+ if (p_clcb->p_srcb == NULL) {
+ p_clcb->p_srcb = bta_gattc_srcb_alloc(remote_bda);
+ }
- if (p_clcb->p_rcb != NULL && p_clcb->p_srcb != NULL) {
- p_clcb->p_srcb->num_clcb++;
- p_clcb->p_rcb->num_clcb++;
- } else {
- /* release this clcb if clcb or srcb allocation failed */
- bta_gattc_cb.clcb_set.erase(p_clcb_i);
- p_clcb = NULL;
- }
+ if (p_clcb->p_rcb != NULL && p_clcb->p_srcb != NULL) {
+ p_clcb->p_srcb->num_clcb++;
+ p_clcb->p_rcb->num_clcb++;
} else {
- for (int i_clcb = 0; i_clcb < BTA_GATTC_CLCB_MAX; i_clcb++) {
- if (!bta_gattc_cb.clcb[i_clcb].in_use) {
-#if (BTA_GATT_DEBUG == TRUE)
- log::verbose("found clcb:{} available", i_clcb);
-#endif
- p_clcb = &bta_gattc_cb.clcb[i_clcb];
- p_clcb->in_use = true;
- p_clcb->status = GATT_SUCCESS;
- p_clcb->transport = transport;
- p_clcb->bda = remote_bda;
- p_clcb->p_q_cmd = NULL;
-
- p_clcb->p_rcb = bta_gattc_cl_get_regcb(client_if);
-
- p_clcb->p_srcb = bta_gattc_find_srcb(remote_bda);
- if (p_clcb->p_srcb == NULL) {
- p_clcb->p_srcb = bta_gattc_srcb_alloc(remote_bda);
- }
-
- if (p_clcb->p_rcb != NULL && p_clcb->p_srcb != NULL) {
- p_clcb->p_srcb->num_clcb++;
- p_clcb->p_rcb->num_clcb++;
- } else {
- /* release this clcb if clcb or srcb allocation failed */
- p_clcb->in_use = false;
- p_clcb = NULL;
- }
- break;
- }
- }
+ /* release this clcb if clcb or srcb allocation failed */
+ bta_gattc_cb.clcb_set.erase(p_clcb_i);
+ p_clcb = NULL;
}
return p_clcb;
}
@@ -330,9 +250,7 @@ void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB* p_clcb) {
p_clcb->status = GATT_SUCCESS;
// in bta_gattc_sm_execute(), p_clcb is accessed again so we dealloc clcb later.
// it will be claned up when the client is deregistered or a new clcb is allocated.
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- bta_gattc_cb.clcb_pending_dealloc.insert(p_clcb);
- }
+ bta_gattc_cb.clcb_pending_dealloc.insert(p_clcb);
}
/*******************************************************************************
@@ -643,39 +561,21 @@ bool bta_gattc_mark_bg_conn(tGATT_IF client_if, const RawAddress& remote_bda_ptr
for (i = 0; i < ble_acceptlist_size(); i++, p_bg_tck++) {
if (p_bg_tck->in_use &&
((p_bg_tck->remote_bda == remote_bda_ptr) || (p_bg_tck->remote_bda.IsEmpty()))) {
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- auto& p_cif_set = p_bg_tck->cif_set;
- if (add) { /* mask on the cif bit */
- p_cif_set.insert(client_if);
- } else {
- if (client_if != 0) {
- p_cif_set.erase(client_if);
- } else {
- p_cif_set.clear();
- }
- }
- /* no BG connection for this device, make it available */
- if (p_bg_tck->cif_set.empty()) {
- p_bg_tck->in_use = false;
- p_bg_tck->remote_bda = RawAddress::kEmpty;
- }
+ auto& p_cif_set = p_bg_tck->cif_set;
+ if (add) { /* mask on the cif bit */
+ p_cif_set.insert(client_if);
} else {
- p_cif_mask = &p_bg_tck->cif_mask;
-
- if (add) { /* mask on the cif bit */
- *p_cif_mask |= (1 << (client_if - 1));
+ if (client_if != 0) {
+ p_cif_set.erase(client_if);
} else {
- if (client_if != 0) {
- *p_cif_mask &= (~(1 << (client_if - 1)));
- } else {
- *p_cif_mask = 0;
- }
- }
- /* no BG connection for this device, make it available */
- if (p_bg_tck->cif_mask == 0) {
- *p_bg_tck = tBTA_GATTC_BG_TCK{};
+ p_cif_set.clear();
}
}
+ /* no BG connection for this device, make it available */
+ if (p_bg_tck->cif_set.empty()) {
+ p_bg_tck->in_use = false;
+ p_bg_tck->remote_bda = RawAddress::kEmpty;
+ }
return true;
}
}
@@ -688,12 +588,7 @@ bool bta_gattc_mark_bg_conn(tGATT_IF client_if, const RawAddress& remote_bda_ptr
p_bg_tck->in_use = true;
p_bg_tck->remote_bda = remote_bda_ptr;
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- p_bg_tck->cif_set = {client_if};
- } else {
- p_cif_mask = &p_bg_tck->cif_mask;
- *p_cif_mask = ((tBTA_GATTC_CIF_MASK)1 << (client_if - 1));
- }
+ p_bg_tck->cif_set = {client_if};
return true;
}
}
@@ -719,15 +614,8 @@ bool bta_gattc_check_bg_conn(tGATT_IF client_if, const RawAddress& remote_bda, u
for (i = 0; i < ble_acceptlist_size() && !is_bg_conn; i++, p_bg_tck++) {
if (p_bg_tck->in_use &&
(p_bg_tck->remote_bda == remote_bda || p_bg_tck->remote_bda.IsEmpty())) {
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- if (p_bg_tck->cif_set.contains(client_if) && role == HCI_ROLE_CENTRAL) {
- is_bg_conn = true;
- }
- } else {
- if (((p_bg_tck->cif_mask & ((tBTA_GATTC_CIF_MASK)1 << (client_if - 1))) != 0) &&
- role == HCI_ROLE_CENTRAL) {
- is_bg_conn = true;
- }
+ if (p_bg_tck->cif_set.contains(client_if) && role == HCI_ROLE_CENTRAL) {
+ is_bg_conn = true;
}
}
}
@@ -938,58 +826,28 @@ void bta_gatt_client_dump(int fd) {
stream << " -- used: " << entry_count << "\n";
entry_count = 0;
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- stream << " ->cl_rcb (dynamic)\n";
- for (auto& [i, p_cl_rcb] : bta_gattc_cb.cl_rcb_map) {
- entry_count++;
- stream << " client_if: " << +p_cl_rcb->client_if << " app uuids: " << p_cl_rcb->app_uuid
- << " clcb_num: " << +p_cl_rcb->num_clcb;
- stream << "\n";
- }
- } else {
- stream << " ->cl_rcb (BTA_GATTC_CL_MAX=" << BTA_GATTC_CL_MAX << ")\n";
- for (int i = 0; i < BTA_GATTC_CL_MAX; i++) {
- tBTA_GATTC_RCB* p_cl_rcb = &bta_gattc_cb.cl_rcb[i];
- if (!p_cl_rcb->in_use) {
- continue;
- }
- entry_count++;
- stream << " client_if: " << +p_cl_rcb->client_if << " app uuids: " << p_cl_rcb->app_uuid
- << " clcb_num: " << +p_cl_rcb->num_clcb;
- stream << "\n";
- }
+ stream << " ->cl_rcb (dynamic)\n";
+ for (auto& [i, p_cl_rcb] : bta_gattc_cb.cl_rcb_map) {
+ entry_count++;
+ stream << " client_if: " << +p_cl_rcb->client_if << " app uuids: " << p_cl_rcb->app_uuid
+ << " clcb_num: " << +p_cl_rcb->num_clcb;
+ stream << "\n";
}
stream << " -- used: " << entry_count << "\n";
entry_count = 0;
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- stream << " ->clcb (dynamic)\n";
- for (auto& p_clcb : bta_gattc_cb.clcb_set) {
- if (!p_clcb->in_use) {
- continue;
- }
- entry_count++;
- stream << " conn_id: " << loghex(p_clcb->bta_conn_id)
- << " address: " << p_clcb->bda.ToRedactedStringForLogging()
- << " transport: " << bt_transport_text(p_clcb->transport)
- << " state: " << bta_clcb_state_text(p_clcb->state);
- stream << "\n";
- }
- } else {
- stream << " ->clcb (BTA_GATTC_CLCB_MAX=" << BTA_GATTC_CLCB_MAX << ")\n";
- for (size_t i = 0; i < BTA_GATTC_CLCB_MAX; i++) {
- tBTA_GATTC_CLCB* p_clcb = &bta_gattc_cb.clcb[i];
- if (!p_clcb->in_use) {
- continue;
- }
- entry_count++;
- stream << " conn_id: " << loghex(p_clcb->bta_conn_id)
- << " address: " << p_clcb->bda.ToRedactedStringForLogging()
- << " transport: " << bt_transport_text(p_clcb->transport)
- << " state: " << bta_clcb_state_text(p_clcb->state);
- stream << "\n";
+ stream << " ->clcb (dynamic)\n";
+ for (auto& p_clcb : bta_gattc_cb.clcb_set) {
+ if (!p_clcb->in_use) {
+ continue;
}
+ entry_count++;
+ stream << " conn_id: " << loghex(p_clcb->bta_conn_id)
+ << " address: " << p_clcb->bda.ToRedactedStringForLogging()
+ << " transport: " << bt_transport_text(p_clcb->transport)
+ << " state: " << bta_clcb_state_text(p_clcb->state);
+ stream << "\n";
}
stream << " -- used: " << entry_count << "\n";
diff --git a/system/bta/hearing_aid/OWNERS b/system/bta/hearing_aid/OWNERS
deleted file mode 100644
index bbaa85ddbb..0000000000
--- a/system/bta/hearing_aid/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_hearingaid
diff --git a/system/bta/hearing_aid/hearing_aid_test.cc b/system/bta/hearing_aid/hearing_aid_test.cc
new file mode 100644
index 0000000000..2090df9d81
--- /dev/null
+++ b/system/bta/hearing_aid/hearing_aid_test.cc
@@ -0,0 +1,474 @@
+/*
+ * Copyright 2025 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.
+ */
+
+#include <base/bind_helpers.h>
+#include <base/functional/bind.h>
+#include <base/strings/string_number_conversions.h>
+#include <bluetooth/log.h>
+#include <com_android_bluetooth_flags.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <osi/include/alarm.h>
+#include <string.h>
+#include <sys/socket.h>
+
+#include <variant>
+
+#include "bta/le_audio/le_audio_types.h"
+#include "bta_gatt_api_mock.h"
+#include "bta_gatt_queue_mock.h"
+#include "bta_hearing_aid_api.h"
+#include "btif_storage_mock.h"
+#include "btm_api_mock.h"
+#include "gatt/database_builder.h"
+#include "hardware/bt_gatt_types.h"
+#include "hci/controller_interface_mock.h"
+#include "stack/include/bt_uuid16.h"
+#include "stack/include/btm_status.h"
+#include "test/common/mock_functions.h"
+#include "test/mock/mock_main_shim_entry.h"
+#include "test/mock/mock_stack_gap_conn_interface.h"
+#include "test/mock/mock_stack_l2cap_interface.h"
+#include "types/bt_transport.h"
+
+static std::map<const char*, bool> fake_osi_bool_props;
+
+namespace bluetooth {
+namespace hearing_aid {
+namespace internal {
+namespace {
+
+using base::HexEncode;
+
+using namespace bluetooth::hearing_aid;
+
+using ::bluetooth::hearing_aid::ConnectionState;
+using ::bluetooth::hearing_aid::HearingAidCallbacks;
+using ::bluetooth::hearing_aid::HearingAidInterface;
+
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::DoAll;
+using ::testing::DoDefault;
+using ::testing::Invoke;
+using ::testing::Mock;
+using ::testing::NiceMock;
+using ::testing::NotNull;
+using ::testing::Return;
+using ::testing::SaveArg;
+using ::testing::Sequence;
+using ::testing::SetArgPointee;
+using ::testing::WithArg;
+
+RawAddress GetTestAddress(int index) {
+ CHECK_LT(index, UINT8_MAX);
+ RawAddress result = {{0xC0, 0xDE, 0xC0, 0xDE, 0x00, static_cast<uint8_t>(index)}};
+ return result;
+}
+
+static uint16_t GetTestConnId(const RawAddress& address) {
+ return address.address[RawAddress::kLength - 1];
+}
+
+class MockHearingAidCallbacks : public HearingAidCallbacks {
+public:
+ MockHearingAidCallbacks() = default;
+ MockHearingAidCallbacks(const MockHearingAidCallbacks&) = delete;
+ ~MockHearingAidCallbacks() override = default;
+
+ MOCK_METHOD((void), OnConnectionState, (ConnectionState state, const RawAddress& address),
+ (override));
+ MOCK_METHOD((void), OnDeviceAvailable,
+ (uint8_t capabilities, uint64_t hiSyncId, const RawAddress& address), (override));
+};
+
+class HearingAidTestBase : public ::testing::Test {
+protected:
+ Uuid HEARING_AID_UUID = Uuid::FromString("FDF0");
+ Uuid READ_ONLY_PROPERTIES_UUID = Uuid::FromString("6333651e-c481-4a3e-9169-7c902aad37bb");
+ Uuid AUDIO_CONTROL_POINT_UUID = Uuid::FromString("f0d4de7e-4a88-476c-9d9f-1937b0996cc0");
+ Uuid AUDIO_STATUS_UUID = Uuid::FromString("38663f1a-e711-4cac-b641-326b56404837");
+ Uuid VOLUME_UUID = Uuid::FromString("00e4ca9e-ab14-41e4-8823-f9e70c7e91df");
+ Uuid LE_PSM_UUID = Uuid::FromString("2d410339-82b6-42aa-b34e-e2e01df8cc1a");
+
+ void set_sample_database(uint16_t conn_id) {
+ static constexpr uint16_t kGapSvcStartHdl = 0x0001;
+ static constexpr uint16_t kGapDeviceNameValHdl = 0x0003;
+ static constexpr uint16_t kGapSvcEndHdl = kGapDeviceNameValHdl;
+
+ static constexpr uint16_t kSvcStartHdl = 0x0010;
+ static constexpr uint16_t kReadOnlyProperties = 0x0012;
+ static constexpr uint16_t kAudioControlPoint = 0x0015;
+ static constexpr uint16_t kAudioStatusPoint = 0x0018;
+ static constexpr uint16_t kVolume = 0x001B;
+ static constexpr uint16_t kLePsm = 0x001E;
+ static constexpr uint16_t kSvcEndHdl = kLePsm;
+
+ gatt::DatabaseBuilder bob;
+
+ /* Generic Access Service */
+ bob.AddService(kGapSvcStartHdl, kGapDeviceNameValHdl, Uuid::From16Bit(0x1800), true);
+ /* Device Name Char. */
+ bob.AddCharacteristic(kGapDeviceNameValHdl - 1, kGapDeviceNameValHdl, Uuid::From16Bit(0x2a00),
+ GATT_CHAR_PROP_BIT_READ);
+
+ /* ASHA Service */
+ bob.AddService(kSvcStartHdl, kSvcEndHdl, HEARING_AID_UUID, true);
+ bob.AddCharacteristic(kReadOnlyProperties - 1, kReadOnlyProperties, READ_ONLY_PROPERTIES_UUID,
+ GATT_CHAR_PROP_BIT_READ);
+ bob.AddCharacteristic(kAudioControlPoint - 1, kAudioControlPoint, AUDIO_CONTROL_POINT_UUID,
+ GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_WRITE_NR);
+ bob.AddCharacteristic(kAudioStatusPoint - 1, kAudioStatusPoint, AUDIO_STATUS_UUID,
+ GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
+ bob.AddDescriptor(kAudioStatusPoint + 1, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
+ bob.AddCharacteristic(kVolume - 1, kVolume, VOLUME_UUID, GATT_CHAR_PROP_BIT_WRITE_NR);
+ bob.AddCharacteristic(kLePsm - 1, kLePsm, LE_PSM_UUID, GATT_CHAR_PROP_BIT_READ);
+
+ services_map[conn_id] = bob.Build().Services();
+
+ ON_CALL(gatt_queue, ReadCharacteristic(conn_id, _, _, _))
+ .WillByDefault(Invoke(
+ [this](uint16_t conn_id, uint16_t handle, GATT_READ_OP_CB cb, void* cb_data) {
+ auto* svc = gatt::FindService(services_map[conn_id], handle);
+ if (svc == nullptr) {
+ return;
+ }
+
+ std::vector<uint8_t> value;
+ tGATT_STATUS status = GATT_SUCCESS;
+
+ switch (handle) {
+ case kReadOnlyProperties:
+ value.resize(17);
+ value.assign(17, 0x01);
+ break;
+ case kAudioStatusPoint:
+ value.resize(1);
+ value.assign(1, 0);
+ break;
+ case kLePsm:
+ value.resize(2);
+ value.assign(2, 0x0080);
+ break;
+ /* passthrough */
+ default:
+ status = GATT_READ_NOT_PERMIT;
+ break;
+ }
+
+ if (cb) {
+ cb(conn_id, status, handle, value.size(), value.data(), cb_data);
+ }
+ }));
+
+ /* default action for GetCharacteristic function call */
+ ON_CALL(gatt_interface, GetCharacteristic(_, _))
+ .WillByDefault(
+ Invoke([&](uint16_t conn_id, uint16_t handle) -> const gatt::Characteristic* {
+ std::list<gatt::Service>& services = services_map[conn_id];
+ for (auto const& service : services) {
+ for (auto const& characteristic : service.characteristics) {
+ if (characteristic.value_handle == handle) {
+ return &characteristic;
+ }
+ }
+ }
+
+ return nullptr;
+ }));
+
+ ON_CALL(gatt_interface, ServiceSearchRequest(_, _))
+ .WillByDefault(WithArg<0>(
+ Invoke([&](uint16_t conn_id) { InjectSearchCompleteEvent(conn_id); })));
+
+ /* default action for GetServices function call */
+ ON_CALL(gatt_interface, GetServices(_))
+ .WillByDefault(WithArg<0>(Invoke([&](uint16_t conn_id) -> std::list<gatt::Service>* {
+ return &services_map[conn_id];
+ })));
+
+ /* default action for RegisterForNotifications function call */
+ ON_CALL(gatt_interface, RegisterForNotifications(gatt_if, _, _))
+ .WillByDefault(Return(GATT_SUCCESS));
+
+ /* default action for DeregisterForNotifications function call */
+ ON_CALL(gatt_interface, DeregisterForNotifications(gatt_if, _, _))
+ .WillByDefault(Return(GATT_SUCCESS));
+
+ /* default action for WriteDescriptor function call */
+ ON_CALL(gatt_queue, WriteDescriptor(_, _, _, _, _, _))
+ .WillByDefault(Invoke([](uint16_t conn_id, uint16_t handle, std::vector<uint8_t> value,
+ tGATT_WRITE_TYPE /*write_type*/, GATT_WRITE_OP_CB cb,
+ void* cb_data) -> void {
+ if (cb) {
+ cb(conn_id, GATT_SUCCESS, handle, value.size(), value.data(), cb_data);
+ }
+ }));
+ }
+
+ void SetUp(void) override {
+ fake_osi_bool_props.clear();
+ bluetooth::manager::SetMockBtmInterface(&btm_interface);
+ bluetooth::storage::SetMockBtifStorageInterface(&btif_storage_interface_);
+ gatt::SetMockBtaGattInterface(&gatt_interface);
+ gatt::SetMockBtaGattQueue(&gatt_queue);
+ callbacks.reset(new MockHearingAidCallbacks());
+ bluetooth::hci::testing::mock_controller_ =
+ std::make_unique<NiceMock<bluetooth::hci::testing::MockControllerInterface>>();
+ bluetooth::testing::stack::l2cap::set_interface(&mock_stack_l2cap_interface_);
+ bluetooth::testing::stack::gap_conn::set_interface(&mock_stack_gap_conn_interface_);
+
+ encryption_result = true;
+
+ ON_CALL(mock_stack_l2cap_interface_, L2CA_UpdateBleConnParams(_, _, _, _, _, _, _))
+ .WillByDefault(Invoke([&](const RawAddress& /*rem_bda*/, uint16_t min_int,
+ uint16_t /*max_int*/, uint16_t latency, uint16_t timeout,
+ uint16_t /*min_ce_len*/, uint16_t /*max_ce_len*/) {
+ req_int = min_int;
+ req_latency = latency;
+ req_timeout = timeout;
+ return true;
+ }));
+
+ ON_CALL(mock_stack_gap_conn_interface_, GAP_ConnOpen(_, _, _, _, _, _, _, _, _, _, _))
+ .WillByDefault(Invoke([&](const char* /* p_serv_name */, uint8_t /*service_id*/,
+ bool /*is_server*/, const RawAddress* p_rem_bda,
+ uint16_t /*psm*/, uint16_t /*le_mps*/,
+ tL2CAP_CFG_INFO* /*p_cfg*/, tL2CAP_ERTM_INFO* /*ertm_info*/,
+ uint16_t /*security*/, tGAP_CONN_CALLBACK* p_cb,
+ tBT_TRANSPORT /*transport*/) {
+ InjectConnUpdateEvent(p_rem_bda->address[5], req_int, req_latency, req_timeout);
+
+ gap_conn_cb = p_cb;
+ if (gap_conn_cb) {
+ gap_conn_cb(0xFFFF, GAP_EVT_CONN_OPENED, nullptr);
+ }
+ return 1;
+ }));
+
+ ON_CALL(mock_stack_gap_conn_interface_, GAP_ConnGetRemoteAddr(_))
+ .WillByDefault(Invoke([&](uint16_t /*gap_handle*/) { return &test_address; }));
+
+ /* by default connect only direct connection requests */
+ ON_CALL(gatt_interface, Open(_, _, _, _))
+ .WillByDefault(Invoke([&](tGATT_IF /*client_if*/, const RawAddress& remote_bda,
+ tBTM_BLE_CONN_TYPE connection_type, bool /*opportunistic*/) {
+ if (connection_type == BTM_BLE_DIRECT_CONNECTION) {
+ InjectConnectedEvent(remote_bda, GetTestConnId(remote_bda));
+ }
+ }));
+
+ ON_CALL(gatt_interface, Close(_)).WillByDefault(Invoke([&](uint16_t conn_id) {
+ /* We arrive here once, when we call Disconnect; and second time, after
+ * we send OnGattDisconnected - but device was already removed */
+ if (connected_devices.count(conn_id) > 0) {
+ InjectDisconnectedEvent(conn_id);
+ }
+ }));
+ }
+
+ void TearDown(void) override {
+ services_map.clear();
+ gatt::SetMockBtaGattQueue(nullptr);
+ gatt::SetMockBtaGattInterface(nullptr);
+ bluetooth::manager::SetMockBtmInterface(nullptr);
+ bluetooth::hci::testing::mock_controller_.reset();
+ bluetooth::testing::stack::l2cap::reset_interface();
+ bluetooth::testing::stack::gap_conn::reset_interface();
+ Mock::VerifyAndClearExpectations(&*callbacks);
+ Mock::VerifyAndClearExpectations(&gatt_queue);
+ Mock::VerifyAndClearExpectations(&gatt_interface);
+ Mock::VerifyAndClearExpectations(&btm_interface);
+ callbacks.reset();
+ }
+
+ void InjectConnectedEvent(const RawAddress& address, uint16_t conn_id,
+ tGATT_STATUS status = GATT_SUCCESS) {
+ tBTA_GATTC_OPEN event_data = {
+ .status = status,
+ .conn_id = conn_id,
+ .client_if = gatt_if,
+ .remote_bda = address,
+ .transport = BT_TRANSPORT_LE,
+ .mtu = 240,
+ };
+ connected_devices[conn_id] = address;
+ gatt_callback(BTA_GATTC_OPEN_EVT, (tBTA_GATTC*)&event_data);
+ }
+
+ void InjectConnUpdateEvent(uint16_t conn_id, uint16_t interval, uint16_t latency,
+ uint16_t timeout, tGATT_STATUS status = GATT_SUCCESS) {
+ tBTA_GATTC_CONN_UPDATE event_data = {
+ .conn_id = conn_id,
+ .interval = interval,
+ .latency = latency,
+ .timeout = timeout,
+ .status = status,
+ };
+
+ gatt_callback(BTA_GATTC_CONN_UPDATE_EVT, (tBTA_GATTC*)&event_data);
+ }
+
+ void InjectDisconnectedEvent(uint16_t conn_id,
+ tGATT_DISCONN_REASON reason = GATT_CONN_TERMINATE_LOCAL_HOST,
+ bool allow_fake_conn = false) {
+ if (!allow_fake_conn) {
+ ASSERT_NE(connected_devices.count(conn_id), 0u);
+ }
+
+ tBTA_GATTC_CLOSE event_data = {
+ .conn_id = conn_id,
+ .status = GATT_SUCCESS,
+ .client_if = gatt_if,
+ .remote_bda = connected_devices[conn_id],
+ .reason = reason,
+ };
+
+ connected_devices.erase(conn_id);
+ gatt_callback(BTA_GATTC_CLOSE_EVT, (tBTA_GATTC*)&event_data);
+ }
+
+ void InjectSearchCompleteEvent(uint16_t conn_id) {
+ tBTA_GATTC_SEARCH_CMPL event_data = {
+ .conn_id = conn_id,
+ .status = GATT_SUCCESS,
+ };
+
+ gatt_callback(BTA_GATTC_SEARCH_CMPL_EVT, (tBTA_GATTC*)&event_data);
+ }
+
+ void InjectNotificationEvent(const RawAddress& test_address, uint16_t conn_id, uint16_t handle,
+ std::vector<uint8_t> value, bool indicate = false) {
+ tBTA_GATTC_NOTIFY event_data = {
+ .conn_id = conn_id,
+ .bda = test_address,
+ .handle = handle,
+ .len = (uint8_t)value.size(),
+ .is_notify = !indicate,
+ };
+
+ ASSERT_TRUE(value.size() < GATT_MAX_ATTR_LEN);
+ std::copy(value.begin(), value.end(), event_data.value);
+ gatt_callback(BTA_GATTC_NOTIF_EVT, (tBTA_GATTC*)&event_data);
+ }
+
+ void SetEncryptionResult(const RawAddress& address, bool success) {
+ encryption_result = success;
+
+ ON_CALL(btm_interface, BTM_IsEncrypted(address, _)).WillByDefault(Return(encryption_result));
+
+ ON_CALL(btm_interface, IsDeviceBonded(address, _)).WillByDefault(Return(true));
+ }
+
+ std::unique_ptr<MockHearingAidCallbacks> callbacks;
+ bluetooth::manager::MockBtmInterface btm_interface;
+ bluetooth::storage::MockBtifStorageInterface btif_storage_interface_;
+ gatt::MockBtaGattInterface gatt_interface;
+ gatt::MockBtaGattQueue gatt_queue;
+ tBTA_GATTC_CBACK* gatt_callback;
+ const uint8_t gatt_if = 0xfe;
+ std::map<uint8_t, RawAddress> connected_devices;
+ std::map<uint16_t, std::list<gatt::Service>> services_map;
+ bluetooth::testing::stack::l2cap::Mock mock_stack_l2cap_interface_;
+ bluetooth::testing::stack::gap_conn::Mock mock_stack_gap_conn_interface_;
+ tGAP_CONN_CALLBACK* gap_conn_cb;
+ uint16_t req_int;
+ uint16_t req_latency;
+ uint16_t req_timeout;
+ bool encryption_result;
+ const RawAddress test_address = GetTestAddress(1);
+};
+
+class HearingAidTest : public HearingAidTestBase {
+ void SetUp(void) override {
+ HearingAidTestBase::SetUp();
+ BtaAppRegisterCallback app_register_callback;
+ EXPECT_CALL(gatt_interface, AppRegister(_, _, _, _))
+ .WillOnce(DoAll(SaveArg<1>(&gatt_callback), SaveArg<2>(&app_register_callback)));
+ HearingAid::Initialize(callbacks.get(), base::DoNothing());
+ ASSERT_TRUE(gatt_callback);
+ ASSERT_TRUE(app_register_callback);
+ app_register_callback.Run(gatt_if, GATT_SUCCESS);
+ ASSERT_TRUE(HearingAid::IsHearingAidRunning());
+ Mock::VerifyAndClearExpectations(&gatt_interface);
+ }
+ void TearDown(void) override {
+ EXPECT_CALL(gatt_interface, AppDeregister(gatt_if));
+ if (HearingAid::IsHearingAidRunning()) {
+ HearingAid::CleanUp();
+ }
+ ASSERT_FALSE(HearingAid::IsHearingAidRunning());
+ gatt_callback = nullptr;
+ HearingAidTestBase::TearDown();
+ }
+};
+
+/* Test that hearing aid is initialized and cleaned up */
+TEST_F(HearingAidTestBase, initialize) {
+ ASSERT_FALSE(HearingAid::IsHearingAidRunning());
+ HearingAid::Initialize(callbacks.get(), base::DoNothing());
+ ASSERT_TRUE(HearingAid::IsHearingAidRunning());
+ HearingAid::CleanUp();
+ ASSERT_FALSE(HearingAid::IsHearingAidRunning());
+}
+
+/* Test that connect cancellation works */
+TEST_F(HearingAidTest, disconnect_when_connecting) {
+ /* Override the default action to prevent us sending the connected event */
+ EXPECT_CALL(gatt_interface, Open(gatt_if, test_address, BTM_BLE_DIRECT_CONNECTION, _))
+ .WillOnce(Return());
+ EXPECT_CALL(*callbacks, OnDeviceAvailable(_, _, test_address)).Times(0);
+ HearingAid::Connect(test_address);
+
+ /* Single call from HearingAid:Disconnect*/
+ EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(1);
+ EXPECT_CALL(gatt_interface, CancelOpen(_, test_address, _)).Times(AnyNumber());
+ EXPECT_CALL(gatt_interface, Close(_)).Times(0);
+ HearingAid::Disconnect(test_address);
+}
+
+/* Test that connect works and Connected state gets reported */
+TEST_F(HearingAidTest, connect) {
+ set_sample_database(1);
+
+ EXPECT_CALL(gatt_interface, Open(gatt_if, test_address, BTM_BLE_DIRECT_CONNECTION, _));
+ EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address));
+ EXPECT_CALL(*callbacks, OnDeviceAvailable(_, _, test_address));
+ ON_CALL(btm_interface, BTM_IsEncrypted(test_address, _)).WillByDefault(Return(true));
+
+ HearingAid::Connect(test_address);
+}
+
+/* Test that connected device can be disconnected */
+TEST_F(HearingAidTest, disconnect_when_connected) {
+ set_sample_database(1);
+
+ ON_CALL(btm_interface, BTM_IsEncrypted(test_address, _)).WillByDefault(Return(true));
+ EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)).Times(1);
+ EXPECT_CALL(*callbacks, OnDeviceAvailable(_, _, test_address));
+ HearingAid::Connect(test_address);
+
+ /* First call from HearingAid:Disconnect. Second call from OnGattDisconnected*/
+ EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(2);
+ EXPECT_CALL(gatt_interface, Close(_)).Times(2);
+ HearingAid::Disconnect(test_address);
+}
+
+} // namespace
+} // namespace internal
+} // namespace hearing_aid
+} // namespace bluetooth
diff --git a/system/bta/hh/bta_hh_le.cc b/system/bta/hh/bta_hh_le.cc
index 6dc6365562..9cbd8569ab 100644
--- a/system/bta/hh/bta_hh_le.cc
+++ b/system/bta/hh/bta_hh_le.cc
@@ -925,14 +925,8 @@ static void bta_hh_le_dis_cback(const RawAddress& addr, tDIS_VALUE* p_dis_value)
p_cb->dscp_info.version = p_dis_value->pnp_id.product_version;
}
- /* TODO(b/367910199): un-serialize once multiservice HoGP is implemented */
- if (com::android::bluetooth::flags::serialize_hogp_and_dis()) {
- Uuid pri_srvc = Uuid::From16Bit(UUID_SERVCLASS_LE_HID);
- BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, pri_srvc);
- return;
- }
-
- bta_hh_le_open_cmpl(p_cb);
+ Uuid pri_srvc = Uuid::From16Bit(UUID_SERVCLASS_LE_HID);
+ BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, pri_srvc);
}
/*******************************************************************************
@@ -950,23 +944,16 @@ static void bta_hh_le_pri_service_discovery(tBTA_HH_DEV_CB* p_cb) {
p_cb->disc_active |= (BTA_HH_LE_DISC_HIDS | BTA_HH_LE_DISC_DIS);
- /* read DIS info */
+ /* read DIS info. If failed, continue to discover HoGP services. */
if (!DIS_ReadDISInfo(p_cb->link_spec.addrt.bda, bta_hh_le_dis_cback, DIS_ATTR_PNP_ID_BIT)) {
log::error("read DIS failed");
p_cb->disc_active &= ~BTA_HH_LE_DISC_DIS;
- } else {
- /* TODO(b/367910199): un-serialize once multiservice HoGP is implemented */
- if (com::android::bluetooth::flags::serialize_hogp_and_dis()) {
- log::debug("Waiting for DIS result before starting HoGP service discovery");
- return;
- }
+ Uuid pri_srvc = Uuid::From16Bit(UUID_SERVCLASS_LE_HID);
+ BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, pri_srvc);
+ return;
}
- /* in parallel */
- /* start primary service discovery for HID service */
- Uuid pri_srvc = Uuid::From16Bit(UUID_SERVCLASS_LE_HID);
- BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, pri_srvc);
- return;
+ log::debug("Waiting for DIS result before starting HoGP service discovery");
}
/*******************************************************************************
@@ -1860,17 +1847,13 @@ static void read_report_cb(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handl
log::warn("Unexpected Read response, w4_evt={}", bta_hh_event_text(p_dev_cb->w4_evt));
return;
}
- if (com::android::bluetooth::flags::forward_get_set_report_failure_to_uhid()) {
- p_dev_cb->w4_evt = BTA_HH_EMPTY_EVT;
- }
+ p_dev_cb->w4_evt = BTA_HH_EMPTY_EVT;
uint8_t hid_handle = p_dev_cb->hid_handle;
const gatt::Characteristic* p_char = BTA_GATTC_GetCharacteristic(conn_id, handle);
if (p_char == nullptr) {
log::error("Unknown handle");
- if (com::android::bluetooth::flags::forward_get_set_report_failure_to_uhid()) {
- send_read_report_reply(hid_handle, BTA_HH_ERR, nullptr);
- }
+ send_read_report_reply(hid_handle, BTA_HH_ERR, nullptr);
return;
}
@@ -1884,16 +1867,10 @@ static void read_report_cb(tCONN_ID conn_id, tGATT_STATUS status, uint16_t handl
break;
default:
log::error("Unexpected Read UUID: {}", p_char->uuid.ToString());
- if (com::android::bluetooth::flags::forward_get_set_report_failure_to_uhid()) {
- send_read_report_reply(hid_handle, BTA_HH_ERR, nullptr);
- }
+ send_read_report_reply(hid_handle, BTA_HH_ERR, nullptr);
return;
}
- if (!com::android::bluetooth::flags::forward_get_set_report_failure_to_uhid()) {
- p_dev_cb->w4_evt = BTA_HH_EMPTY_EVT;
- }
-
if (status != GATT_SUCCESS) {
send_read_report_reply(hid_handle, BTA_HH_ERR, nullptr);
return;
@@ -1937,9 +1914,7 @@ static void bta_hh_le_get_rpt(tBTA_HH_DEV_CB* p_cb, tBTA_HH_RPT_TYPE r_type, uin
if (p_rpt == nullptr) {
log::error("no matching report");
- if (com::android::bluetooth::flags::forward_get_set_report_failure_to_uhid()) {
- send_read_report_reply(p_cb->hid_handle, BTA_HH_ERR, nullptr);
- }
+ send_read_report_reply(p_cb->hid_handle, BTA_HH_ERR, nullptr);
return;
}
@@ -1982,17 +1957,13 @@ static void write_report_cb(tCONN_ID conn_id, tGATT_STATUS status, uint16_t hand
}
log::verbose("w4_evt:{}", bta_hh_event_text(p_dev_cb->w4_evt));
- if (com::android::bluetooth::flags::forward_get_set_report_failure_to_uhid()) {
- p_dev_cb->w4_evt = BTA_HH_EMPTY_EVT;
- }
+ p_dev_cb->w4_evt = BTA_HH_EMPTY_EVT;
uint8_t hid_handle = p_dev_cb->hid_handle;
const gatt::Characteristic* p_char = BTA_GATTC_GetCharacteristic(conn_id, handle);
if (p_char == nullptr) {
log::error("Unknown characteristic handle: {}", handle);
- if (com::android::bluetooth::flags::forward_get_set_report_failure_to_uhid()) {
- send_write_report_reply(hid_handle, BTA_HH_ERR, cb_evt);
- }
+ send_write_report_reply(hid_handle, BTA_HH_ERR, cb_evt);
return;
}
@@ -2000,17 +1971,10 @@ static void write_report_cb(tCONN_ID conn_id, tGATT_STATUS status, uint16_t hand
if (uuid16 != GATT_UUID_HID_REPORT && uuid16 != GATT_UUID_HID_BT_KB_INPUT &&
uuid16 != GATT_UUID_HID_BT_MOUSE_INPUT && uuid16 != GATT_UUID_HID_BT_KB_OUTPUT) {
log::error("Unexpected characteristic UUID: {}", p_char->uuid.ToString());
- if (com::android::bluetooth::flags::forward_get_set_report_failure_to_uhid()) {
- send_write_report_reply(hid_handle, BTA_HH_ERR, cb_evt);
- }
+ send_write_report_reply(hid_handle, BTA_HH_ERR, cb_evt);
return;
}
- /* Set Report finished */
- if (!com::android::bluetooth::flags::forward_get_set_report_failure_to_uhid()) {
- p_dev_cb->w4_evt = BTA_HH_EMPTY_EVT;
- }
-
if (status == GATT_SUCCESS) {
send_write_report_reply(hid_handle, BTA_HH_OK, cb_evt);
} else {
@@ -2033,9 +1997,7 @@ static void bta_hh_le_write_rpt(tBTA_HH_DEV_CB* p_cb, tBTA_HH_RPT_TYPE r_type, B
if (p_buf == NULL || p_buf->len == 0) {
log::error("Illegal data");
- if (com::android::bluetooth::flags::forward_get_set_report_failure_to_uhid()) {
- send_write_report_reply(p_cb->hid_handle, BTA_HH_ERR, w4_evt);
- }
+ send_write_report_reply(p_cb->hid_handle, BTA_HH_ERR, w4_evt);
return;
}
@@ -2047,9 +2009,7 @@ static void bta_hh_le_write_rpt(tBTA_HH_DEV_CB* p_cb, tBTA_HH_RPT_TYPE r_type, B
p_rpt = bta_hh_le_find_rpt_by_idtype(p_cb->hid_srvc.report, p_cb->mode, r_type, rpt_id);
if (p_rpt == NULL) {
log::error("no matching report");
- if (com::android::bluetooth::flags::forward_get_set_report_failure_to_uhid()) {
- send_write_report_reply(p_cb->hid_handle, BTA_HH_ERR, w4_evt);
- }
+ send_write_report_reply(p_cb->hid_handle, BTA_HH_ERR, w4_evt);
osi_free(p_buf);
return;
}
diff --git a/system/bta/include/OWNERS b/system/bta/include/OWNERS
deleted file mode 100644
index 9dfb8422a1..0000000000
--- a/system/bta/include/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-per-file bta_hearing_aid_api.h=file:/OWNERS_hearingaid
diff --git a/system/bta/le_audio/OWNERS b/system/bta/le_audio/OWNERS
deleted file mode 100644
index a7d77894ba..0000000000
--- a/system/bta/le_audio/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_leaudio
diff --git a/system/bta/le_audio/broadcaster/broadcaster_test.cc b/system/bta/le_audio/broadcaster/broadcaster_test.cc
index a211a810ad..16177230d1 100644
--- a/system/bta/le_audio/broadcaster/broadcaster_test.cc
+++ b/system/bta/le_audio/broadcaster/broadcaster_test.cc
@@ -63,6 +63,8 @@ using testing::Test;
using namespace bluetooth::le_audio;
using namespace bluetooth;
+using bluetooth::hci::testing::mock_controller_;
+
using bluetooth::le_audio::DsaMode;
using bluetooth::le_audio::LeAudioCodecConfiguration;
using bluetooth::le_audio::LeAudioSourceAudioHalClient;
@@ -287,8 +289,8 @@ protected:
init_message_loop_thread();
reset_mock_function_count_map();
- bluetooth::hci::testing::mock_controller_ = &mock_controller_;
- ON_CALL(mock_controller_, SupportsBleIsochronousBroadcaster).WillByDefault(Return(true));
+ mock_controller_ = std::make_unique<bluetooth::hci::testing::MockControllerInterface>();
+ ON_CALL(*mock_controller_, SupportsBleIsochronousBroadcaster).WillByDefault(Return(true));
iso_manager_ = bluetooth::hci::IsoManager::GetInstance();
ASSERT_NE(iso_manager_, nullptr);
@@ -366,7 +368,7 @@ protected:
ContentControlIdKeeper::GetInstance()->Stop();
- bluetooth::hci::testing::mock_controller_ = nullptr;
+ bluetooth::hci::testing::mock_controller_.release();
delete mock_audio_source_;
iso_active_callback = nullptr;
delete mock_audio_source_;
@@ -436,7 +438,6 @@ protected:
protected:
MockLeAudioBroadcasterCallbacks mock_broadcaster_callbacks_;
- bluetooth::hci::testing::MockControllerInterface mock_controller_;
bluetooth::hci::IsoManager* iso_manager_;
MockIsoManager* mock_iso_manager_;
bluetooth::hci::iso_manager::BigCallbacks* big_callbacks_ = nullptr;
diff --git a/system/bta/le_audio/codec_manager.cc b/system/bta/le_audio/codec_manager.cc
index 9452218c5d..104d397833 100644
--- a/system/bta/le_audio/codec_manager.cc
+++ b/system/bta/le_audio/codec_manager.cc
@@ -733,11 +733,11 @@ public:
bool AppendStreamMapExtension(const std::vector<struct types::cis>& cises,
const stream_parameters& stream_params, uint8_t direction) {
- // In the legacy mode we are already done
- if (!IsUsingCodecExtensibility()) {
- log::verbose("Codec Extensibility is disabled");
- return true;
- }
+ /* Without the codec extensibility enabled, we still need the BT stack structure to
+ * have the valid extended codec configuration entries, as these are used for codec type
+ * matching. The extended data fields of the AIDL API data structures are filed
+ * right before the AIDL call, only if the codec extensibility is enabled
+ */
const std::string tag =
types::BidirectionalPair<std::string>({.sink = "Sink", .source = "Source"})
diff --git a/system/bta/le_audio/codec_manager_test.cc b/system/bta/le_audio/codec_manager_test.cc
index b8f79a609b..c69464b72e 100644
--- a/system/bta/le_audio/codec_manager_test.cc
+++ b/system/bta/le_audio/codec_manager_test.cc
@@ -300,10 +300,12 @@ public:
bluetooth::legacy::hci::testing::SetMock(legacy_hci_mock_);
- ON_CALL(controller_interface, SupportsBleIsochronousBroadcaster).WillByDefault(Return(true));
- ON_CALL(controller_interface, IsSupported(OpCode::CONFIGURE_DATA_PATH))
+ bluetooth::hci::testing::mock_controller_ =
+ std::make_unique<NiceMock<bluetooth::hci::testing::MockControllerInterface>>();
+ ON_CALL(*bluetooth::hci::testing::mock_controller_, SupportsBleIsochronousBroadcaster)
+ .WillByDefault(Return(true));
+ ON_CALL(*bluetooth::hci::testing::mock_controller_, IsSupported(OpCode::CONFIGURE_DATA_PATH))
.WillByDefault(Return(true));
- bluetooth::hci::testing::mock_controller_ = &controller_interface;
codec_manager = CodecManager::GetInstance();
@@ -311,9 +313,11 @@ public:
RegisterSinkHalClientMock();
}
- virtual void TearDown() override { codec_manager->Stop(); }
+ virtual void TearDown() override {
+ codec_manager->Stop();
+ bluetooth::hci::testing::mock_controller_.release();
+ }
- NiceMock<bluetooth::hci::testing::MockControllerInterface> controller_interface;
CodecManager* codec_manager;
bluetooth::legacy::hci::testing::MockInterface legacy_hci_mock_;
@@ -559,15 +563,16 @@ TEST_F(CodecManagerTestAdsp, testStreamConfigurationMono) {
};
// Stream parameters
+ auto stream_map_entry_mono_bidir =
+ stream_map_info(97, codec_spec_conf::kLeAudioLocationMonoAudio, true);
+ stream_map_entry_mono_bidir.codec_config.id = kLeAudioCodecIdLc3;
types::BidirectionalPair<stream_parameters> stream_params{
.sink =
{
.audio_channel_allocation = codec_spec_conf::kLeAudioLocationMonoAudio,
.stream_config =
{
- .stream_map = {stream_map_info(
- 97, codec_spec_conf::kLeAudioLocationMonoAudio,
- true)},
+ .stream_map = {stream_map_entry_mono_bidir},
.bits_per_sample = 16,
.sampling_frequency_hz = 16000,
.frame_duration_us = 10000,
@@ -583,9 +588,7 @@ TEST_F(CodecManagerTestAdsp, testStreamConfigurationMono) {
.audio_channel_allocation = codec_spec_conf::kLeAudioLocationMonoAudio,
.stream_config =
{
- .stream_map = {stream_map_info(
- 97, codec_spec_conf::kLeAudioLocationMonoAudio,
- true)},
+ .stream_map = {stream_map_entry_mono_bidir},
.bits_per_sample = 16,
.sampling_frequency_hz = 16000,
.frame_duration_us = 10000,
@@ -628,6 +631,7 @@ TEST_F(CodecManagerTestAdsp, testStreamConfigurationMono) {
ASSERT_EQ(codec_spec_conf::kLeAudioLocationMonoAudio, info.audio_channel_allocation);
// The connected should be active
ASSERT_TRUE(info.is_stream_active);
+ ASSERT_EQ(info.codec_config.id.coding_format, kLeAudioCodecIdLc3.coding_format);
} else {
ASSERT_EQ(97, info.stream_handle);
diff --git a/system/bta/le_audio/devices_test.cc b/system/bta/le_audio/devices_test.cc
index adc90e5213..cd711065c4 100644
--- a/system/bta/le_audio/devices_test.cc
+++ b/system/bta/le_audio/devices_test.cc
@@ -514,7 +514,9 @@ protected:
desired_group_size_ = -1;
bluetooth::manager::SetMockBtmInterface(&btm_interface_);
- bluetooth::hci::testing::mock_controller_ = &controller_interface_;
+
+ bluetooth::hci::testing::mock_controller_ =
+ std::make_unique<NiceMock<bluetooth::hci::testing::MockControllerInterface>>();
auto codec_location = ::bluetooth::le_audio::types::CodecLocation::HOST;
bluetooth::le_audio::AudioSetConfigurationProvider::Initialize(codec_location);
@@ -740,6 +742,8 @@ protected:
if (codec_manager_) {
codec_manager_->Stop();
}
+
+ bluetooth::hci::testing::mock_controller_.reset();
}
LeAudioDevice* AddTestDevice(int snk_ase_num, int src_ase_num, int snk_ase_num_cached = 0,
@@ -1417,7 +1421,6 @@ protected:
LeAudioDeviceGroup* group_ = nullptr;
bluetooth::manager::MockBtmInterface btm_interface_;
MockCsisClient mock_csis_client_module_;
- NiceMock<bluetooth::hci::testing::MockControllerInterface> controller_interface_;
bluetooth::le_audio::CodecManager* codec_manager_;
MockCodecManager* mock_codec_manager_;
diff --git a/system/bta/le_audio/le_audio_client_test.cc b/system/bta/le_audio/le_audio_client_test.cc
index a3c52dc9e6..02104518d2 100644
--- a/system/bta/le_audio/le_audio_client_test.cc
+++ b/system/bta/le_audio/le_audio_client_test.cc
@@ -1477,11 +1477,13 @@ protected:
init_message_loop_thread();
reset_mock_function_count_map();
- ON_CALL(controller_, SupportsBleConnectedIsochronousStreamCentral).WillByDefault(Return(true));
- ON_CALL(controller_, SupportsBleConnectedIsochronousStreamPeripheral)
+ hci::testing::mock_controller_ =
+ std::make_unique<NiceMock<bluetooth::hci::testing::MockControllerInterface>>();
+ ON_CALL(*hci::testing::mock_controller_, SupportsBleConnectedIsochronousStreamCentral)
.WillByDefault(Return(true));
- ON_CALL(controller_, SupportsBle2mPhy).WillByDefault(Return(true));
- bluetooth::hci::testing::mock_controller_ = &controller_;
+ ON_CALL(*hci::testing::mock_controller_, SupportsBleConnectedIsochronousStreamPeripheral)
+ .WillByDefault(Return(true));
+ ON_CALL(*hci::testing::mock_controller_, SupportsBle2mPhy).WillByDefault(Return(true));
bluetooth::manager::SetMockBtmInterface(&mock_btm_interface_);
gatt::SetMockBtaGattInterface(&mock_gatt_interface_);
gatt::SetMockBtaGattQueue(&mock_gatt_queue_);
@@ -1595,7 +1597,7 @@ protected:
}
iso_manager_->Stop();
- bluetooth::hci::testing::mock_controller_ = nullptr;
+ hci::testing::mock_controller_.reset();
}
protected:
@@ -2761,7 +2763,6 @@ protected:
/* Audio track metadata */
char* test_tags_ptr_ = nullptr;
- NiceMock<bluetooth::hci::testing::MockControllerInterface> controller_;
};
class UnicastTest : public UnicastTestNoInit {
diff --git a/system/bta/le_audio/metrics_collector.cc b/system/bta/le_audio/metrics_collector.cc
index a4fb4a353d..24da2e085c 100644
--- a/system/bta/le_audio/metrics_collector.cc
+++ b/system/bta/le_audio/metrics_collector.cc
@@ -25,9 +25,9 @@
#include <unordered_map>
#include <vector>
-#include "common/metrics.h"
#include "hardware/bt_le_audio.h"
#include "le_audio_types.h"
+#include "os/metrics.h"
#include "types/raw_address.h"
namespace bluetooth::le_audio {
@@ -199,7 +199,7 @@ public:
device_address[i] = device_metric->address_;
}
- bluetooth::common::LogLeAudioConnectionSessionReported(
+ bluetooth::os::LogMetricLeAudioConnectionSessionReported(
group_size_, group_id_, connection_duration_nanos, device_connecting_offset_nanos,
device_connected_offset_nanos, device_connection_duration_nanos,
device_connection_statuses, device_disconnection_statuses, device_address,
@@ -278,7 +278,7 @@ void MetricsCollector::OnBroadcastStateChanged(bool started) {
broadcast_beginning_timepoint_ = std::chrono::high_resolution_clock::now();
} else {
auto broadcast_ending_timepoint_ = std::chrono::high_resolution_clock::now();
- bluetooth::common::LogLeAudioBroadcastSessionReported(
+ bluetooth::os::LogMetricLeAudioBroadcastSessionReported(
get_timedelta_nanos(broadcast_beginning_timepoint_, broadcast_ending_timepoint_));
broadcast_beginning_timepoint_ = kInvalidTimePoint;
}
diff --git a/system/bta/le_audio/metrics_collector_test.cc b/system/bta/le_audio/metrics_collector_test.cc
index c94db90ad6..199199bf8a 100644
--- a/system/bta/le_audio/metrics_collector_test.cc
+++ b/system/bta/le_audio/metrics_collector_test.cc
@@ -23,7 +23,7 @@
#include <cstdint>
#include <vector>
-#include "common/metrics.h"
+#include "os/metrics.h"
#include "types/raw_address.h"
using testing::_;
@@ -57,9 +57,9 @@ std::vector<int64_t> last_streaming_duration_nanos;
std::vector<int32_t> last_streaming_context_type;
namespace bluetooth {
-namespace common {
+namespace os {
-void LogLeAudioConnectionSessionReported(
+void LogMetricLeAudioConnectionSessionReported(
int32_t group_size, int32_t group_metric_id, int64_t connection_duration_nanos,
const std::vector<int64_t>& device_connecting_offset_nanos,
const std::vector<int64_t>& device_connected_offset_nanos,
@@ -85,11 +85,11 @@ void LogLeAudioConnectionSessionReported(
last_streaming_context_type = streaming_context_type;
}
-void LogLeAudioBroadcastSessionReported(int64_t duration_nanos) {
+void LogMetricLeAudioBroadcastSessionReported(int64_t duration_nanos) {
last_broadcast_duration_nanos = duration_nanos;
}
-} // namespace common
+} // namespace os
} // namespace bluetooth
namespace bluetooth::le_audio {
diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc
index e5ce67cf9d..b3f20fba39 100644
--- a/system/bta/le_audio/state_machine.cc
+++ b/system/bta/le_audio/state_machine.cc
@@ -681,8 +681,16 @@ public:
kLogHciEvent, group->group_id_, leAudioDevice->address_,
kLogSetDataPathOp + "cis_h:" + loghex(conn_handle) + " STATUS=" + loghex(status));
+ /* Find ASE and later update state for the given cis.*/
+ auto ase = leAudioDevice->GetFirstActiveAseByCisAndDataPathState(CisState::CONNECTED,
+ DataPathState::CONFIGURING);
+
if (status) {
- log::error("failed to setup data path");
+ log::error("Failed to setup data path for {}, cis handle: {:#x}, error: {:#x}",
+ leAudioDevice->address_, conn_handle, status);
+ if (ase && ase->cis_conn_hdl == conn_handle) {
+ ase->data_path_state = DataPathState::IDLE;
+ }
StopStream(group);
return;
@@ -696,10 +704,6 @@ public:
return;
}
- /* Update state for the given cis.*/
- auto ase = leAudioDevice->GetFirstActiveAseByCisAndDataPathState(CisState::CONNECTED,
- DataPathState::CONFIGURING);
-
if (!ase || ase->cis_conn_hdl != conn_handle) {
log::error("Cannot find ase by handle {}", conn_handle);
return;
diff --git a/system/bta/le_audio/state_machine_test.cc b/system/bta/le_audio/state_machine_test.cc
index d17bfda188..e0860515fb 100644
--- a/system/bta/le_audio/state_machine_test.cc
+++ b/system/bta/le_audio/state_machine_test.cc
@@ -261,7 +261,9 @@ protected:
bluetooth::manager::SetMockBtmInterface(&btm_interface);
gatt::SetMockBtaGattInterface(&gatt_interface);
gatt::SetMockBtaGattQueue(&gatt_queue);
- bluetooth::hci::testing::mock_controller_ = &controller_;
+
+ bluetooth::hci::testing::mock_controller_ =
+ std::make_unique<bluetooth::hci::testing::MockControllerInterface>();
overwrite_cis_status_idx_ = 0;
use_cis_retry_cnt_ = false;
@@ -649,7 +651,7 @@ protected:
cached_remote_qos_configuration_for_ase_.clear();
LeAudioGroupStateMachine::Cleanup();
::bluetooth::le_audio::AudioSetConfigurationProvider::Cleanup();
- bluetooth::hci::testing::mock_controller_ = nullptr;
+ bluetooth::hci::testing::mock_controller_.release();
}
std::shared_ptr<LeAudioDevice> PrepareConnectedDevice(uint8_t id,
@@ -1714,7 +1716,6 @@ protected:
std::vector<RawAddress> addresses_;
std::map<uint8_t, std::unique_ptr<LeAudioDeviceGroup>> le_audio_device_groups_;
bool group_create_command_disallowed_ = false;
- bluetooth::hci::testing::MockControllerInterface controller_;
};
class StateMachineTest : public StateMachineTestBase {
diff --git a/system/bta/test/bta_ag_sco_test.cc b/system/bta/test/bta_ag_sco_test.cc
index 16caac7665..a90198c54a 100644
--- a/system/bta/test/bta_ag_sco_test.cc
+++ b/system/bta/test/bta_ag_sco_test.cc
@@ -43,14 +43,14 @@ protected:
this->codec = codec;
return enh_esco_params_t{};
};
- bluetooth::hci::testing::mock_controller_ = &controller_;
+ bluetooth::hci::testing::mock_controller_ =
+ std::make_unique<bluetooth::hci::testing::MockControllerInterface>();
}
void TearDown() override {
test::mock::device_esco_parameters::esco_parameters_for_codec = {};
- bluetooth::hci::testing::mock_controller_ = nullptr;
+ bluetooth::hci::testing::mock_controller_.reset();
}
esco_codec_t codec;
- bluetooth::hci::testing::MockControllerInterface controller_;
};
TEST_P(BtaAgScoParameterSelectionTest, create_sco_cvsd) {
diff --git a/system/bta/test/bta_ag_test.cc b/system/bta/test/bta_ag_test.cc
index 5fa3884669..2114f7e773 100644
--- a/system/bta/test/bta_ag_test.cc
+++ b/system/bta/test/bta_ag_test.cc
@@ -65,7 +65,8 @@ protected:
void SetUp() override {
reset_mock_function_count_map();
fake_osi_ = std::make_unique<test::fake::FakeOsi>();
- bluetooth::hci::testing::mock_controller_ = &controller_;
+ bluetooth::hci::testing::mock_controller_ =
+ std::make_unique<bluetooth::hci::testing::MockControllerInterface>();
main_thread_start_up();
post_on_bt_main([]() { log::info("Main thread started up"); });
@@ -85,7 +86,7 @@ protected:
bta_sys_deregister(BTA_ID_AG);
post_on_bt_main([]() { log::info("Main thread shutting down"); });
main_thread_shut_down();
- bluetooth::hci::testing::mock_controller_ = nullptr;
+ bluetooth::hci::testing::mock_controller_.reset();
}
std::unique_ptr<test::fake::FakeOsi> fake_osi_;
@@ -93,7 +94,6 @@ protected:
uint32_t tmp_num = 0xFFFF;
RawAddress addr;
esco_codec_t codec;
- bluetooth::hci::testing::MockControllerInterface controller_;
};
class BtaAgSwbTest : public BtaAgTest {
diff --git a/system/bta/test/bta_dm_test.cc b/system/bta/test/bta_dm_test.cc
index 90d41d5e6f..b49008b739 100644
--- a/system/bta/test/bta_dm_test.cc
+++ b/system/bta/test/bta_dm_test.cc
@@ -65,10 +65,10 @@ class BtaDmTest : public BtaWithContextTest {
protected:
void SetUp() override {
BtaWithContextTest::SetUp();
- ON_CALL(controller_, LeRand).WillByDefault([](bluetooth::hci::LeRandCallback cb) {
- cb(0x1234);
- });
- bluetooth::hci::testing::mock_controller_ = &controller_;
+ bluetooth::hci::testing::mock_controller_ =
+ std::make_unique<bluetooth::hci::testing::MockControllerInterface>();
+ ON_CALL(*bluetooth::hci::testing::mock_controller_, LeRand)
+ .WillByDefault([](bluetooth::hci::LeRandCallback cb) { cb(0x1234); });
BTA_dm_init();
bluetooth::legacy::testing::bta_dm_init_cb();
@@ -82,9 +82,8 @@ protected:
void TearDown() override {
bluetooth::legacy::testing::bta_dm_deinit_cb();
BtaWithContextTest::TearDown();
- bluetooth::hci::testing::mock_controller_ = nullptr;
+ bluetooth::hci::testing::mock_controller_.reset();
}
- bluetooth::hci::testing::MockControllerInterface controller_;
};
class BtaDmCustomAlarmTest : public BtaDmTest {
diff --git a/system/bta/test/bta_sdp_test.cc b/system/bta/test/bta_sdp_test.cc
index 06e8ff86aa..77f1762cc0 100644
--- a/system/bta/test/bta_sdp_test.cc
+++ b/system/bta/test/bta_sdp_test.cc
@@ -30,17 +30,16 @@ class BtaSdpTest : public BtaWithHwOnTest {
protected:
void SetUp() override {
BtaWithHwOnTest::SetUp();
- ON_CALL(controller_, LeRand).WillByDefault([](bluetooth::hci::LeRandCallback cb) {
- cb(0x1234);
- });
- bluetooth::hci::testing::mock_controller_ = &controller_;
+ bluetooth::hci::testing::mock_controller_ =
+ std::make_unique<bluetooth::hci::testing::MockControllerInterface>();
+ ON_CALL(*bluetooth::hci::testing::mock_controller_, LeRand)
+ .WillByDefault([](bluetooth::hci::LeRandCallback cb) { cb(0x1234); });
}
void TearDown() override {
BtaWithHwOnTest::TearDown();
- bluetooth::hci::testing::mock_controller_ = nullptr;
+ bluetooth::hci::testing::mock_controller_.reset();
}
- bluetooth::hci::testing::MockControllerInterface controller_;
};
class BtaSdpRegisteredTest : public BtaSdpTest {
diff --git a/system/bta/test/bta_test_fixtures.h b/system/bta/test/bta_test_fixtures.h
index c259d0b916..e41e64d496 100644
--- a/system/bta/test/bta_test_fixtures.h
+++ b/system/bta/test/bta_test_fixtures.h
@@ -60,7 +60,8 @@ protected:
ASSERT_NE(get_btm_client_interface().lifecycle.btm_init, nullptr);
ASSERT_NE(get_btm_client_interface().lifecycle.btm_free, nullptr);
- bluetooth::hci::testing::mock_controller_ = &mock_controller_;
+ bluetooth::hci::testing::mock_controller_ =
+ std::make_unique<bluetooth::hci::testing::MockControllerInterface>();
bluetooth::testing::stack::rnr::set_interface(&mock_stack_rnr_interface_);
test::mock::stack_gatt_api::GATT_Register.body =
@@ -85,12 +86,11 @@ protected:
mock_btm_client_interface.eir.BTM_WriteEIR = {};
bluetooth::testing::stack::rnr::reset_interface();
- bluetooth::hci::testing::mock_controller_ = nullptr;
+ bluetooth::hci::testing::mock_controller_.reset();
BtaWithFakesTest::TearDown();
}
- bluetooth::hci::testing::MockControllerInterface mock_controller_;
bluetooth::testing::stack::rnr::Mock mock_stack_rnr_interface_;
};
diff --git a/system/bta/test/common/btif_storage_mock.cc b/system/bta/test/common/btif_storage_mock.cc
index 7e4a4e5118..f5eb38939e 100644
--- a/system/bta/test/common/btif_storage_mock.cc
+++ b/system/bta/test/common/btif_storage_mock.cc
@@ -19,6 +19,7 @@
#include <bluetooth/log.h>
+#include "bta_hearing_aid_api.h"
#include "btif/include/btif_profile_storage.h"
#include "btif/include/btif_storage.h"
@@ -134,3 +135,17 @@ bt_status_t btif_storage_get_remote_device_property(const RawAddress* address,
log::assert_that(btif_storage_interface != nullptr, "Mock storage module not set!");
return btif_storage_interface->GetRemoteDeviceProperty(address, property);
}
+
+/** Get the hearing aid device properties. */
+bool btif_storage_get_hearing_aid_prop(const RawAddress& address, uint8_t* capabilities,
+ uint64_t* hi_sync_id, uint16_t* render_delay,
+ uint16_t* preparation_delay, uint16_t* codecs) {
+ log::assert_that(btif_storage_interface != nullptr, "Mock storage module not set!");
+ return btif_storage_interface->GetHearingAidProp(address, capabilities, hi_sync_id, render_delay,
+ preparation_delay, codecs);
+}
+
+void btif_storage_add_hearing_aid(const HearingDevice& dev_info) {
+ log::assert_that(btif_storage_interface != nullptr, "Mock storage module not set!");
+ return btif_storage_interface->AddHearingAid(&dev_info);
+}
diff --git a/system/bta/test/common/btif_storage_mock.h b/system/bta/test/common/btif_storage_mock.h
index 8809643f70..25f9bbdde0 100644
--- a/system/bta/test/common/btif_storage_mock.h
+++ b/system/bta/test/common/btif_storage_mock.h
@@ -21,6 +21,8 @@
#include "include/hardware/bluetooth.h"
#include "types/raw_address.h"
+struct HearingDevice;
+
namespace bluetooth {
namespace storage {
@@ -50,6 +52,11 @@ public:
virtual bt_status_t GetRemoteDeviceProperty(const RawAddress* address,
bt_property_t* property) = 0;
+ virtual bool GetHearingAidProp(const RawAddress& address, uint8_t* capabilities,
+ uint64_t* hi_sync_id, uint16_t* render_delay,
+ uint16_t* preparation_delay, uint16_t* codecs) = 0;
+ virtual void AddHearingAid(const HearingDevice* dev_info) = 0;
+
virtual ~BtifStorageInterface() = default;
};
@@ -88,6 +95,11 @@ public:
MOCK_METHOD((void), RemoveLeaudioHas, (const RawAddress& address), (override));
MOCK_METHOD((bt_status_t), GetRemoteDeviceProperty,
(const RawAddress* address, bt_property_t* property), (override));
+ MOCK_METHOD((bool), GetHearingAidProp,
+ (const RawAddress& address, uint8_t* capabilities, uint64_t* hi_sync_id,
+ uint16_t* render_delay, uint16_t* preparation_delay, uint16_t* codecs),
+ (override));
+ MOCK_METHOD((void), AddHearingAid, (const HearingDevice* dev_info), (override));
};
/**
diff --git a/system/btcore/Android.bp b/system/btcore/Android.bp
index 6a0350afcb..b02ead0f8d 100644
--- a/system/btcore/Android.bp
+++ b/system/btcore/Android.bp
@@ -20,10 +20,8 @@ cc_library_static {
"packages/modules/Bluetooth/system/gd",
],
srcs: [
- "src/device_class.cc",
"src/module.cc",
"src/osi_module.cc",
- "src/property.cc",
],
header_libs: ["libbluetooth_headers"],
static_libs: [
@@ -50,41 +48,3 @@ cc_library_headers {
],
min_sdk_version: "30",
}
-
-// Note: It's good to get the tests compiled both for the host and the target so
-// we get to test with both Bionic libc and glibc
-// libbtcore unit tests for target and host
-cc_test {
- name: "net_test_btcore",
- test_suites: ["general-tests"],
- defaults: [
- "fluoride_defaults",
- "mts_defaults",
- ],
- local_include_dirs: ["include"],
- include_dirs: ["packages/modules/Bluetooth/system"],
- srcs: [
- "test/device_class_test.cc",
- "test/property_test.cc",
- ],
- shared_libs: [
- "libbase",
- "liblog",
- ],
- static_libs: [
- "libbluetooth-types",
- "libbluetooth_log",
- "libbtcore",
- "libchrome",
- "libcom.android.sysprop.bluetooth.wrapped",
- "libosi",
- ],
- host_supported: true,
- test_options: {
- unit_test: true,
- },
- sanitize: {
- address: true,
- },
- header_libs: ["libbluetooth_headers"],
-}
diff --git a/system/btcore/BUILD.gn b/system/btcore/BUILD.gn
index 76853554cf..abfbd328ee 100644
--- a/system/btcore/BUILD.gn
+++ b/system/btcore/BUILD.gn
@@ -16,11 +16,9 @@
static_library("btcore") {
sources = [
- "src/device_class.cc",
"src/hal_util.cc",
"src/module.cc",
"src/osi_module.cc",
- "src/property.cc",
]
include_dirs = [
@@ -33,35 +31,3 @@ static_library("btcore") {
"//bt/system/log:log_defaults",
]
}
-
-if (use.test) {
- executable("net_test_btcore") {
- sources = [
- "test/device_class_test.cc",
- "test/property_test.cc",
- ]
-
- include_dirs = [
- "include",
- "//bt/system",
- ]
-
- deps = [
- "//bt/system/btcore",
- "//bt/system/osi",
- "//bt/system/types",
- ]
-
- configs += [
- "//bt/system:external_gtest_main",
- "//bt/system:target_defaults",
- "//bt/system/log:log_defaults",
- ]
-
- libs = [
- "pthread",
- "rt",
- "dl",
- ]
- }
-}
diff --git a/system/btcore/fuzzer/Android.bp b/system/btcore/fuzzer/Android.bp
deleted file mode 100644
index 07b8c28f89..0000000000
--- a/system/btcore/fuzzer/Android.bp
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2021 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 {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "system_bt_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["system_bt_license"],
-}
-
-cc_defaults {
- name: "btcore_fuzz_defaults",
- shared_libs: [
- "libcrypto",
- "libstatslog_bt",
- ],
- static_libs: [
- "libbase",
- "libbluetooth-types",
- "libbluetooth_crypto_toolbox",
- "libbluetooth_log",
- "libbt-common",
- "libbtcore",
- "libchrome",
- "libcom.android.sysprop.bluetooth.wrapped",
- "libevent",
- "liblog",
- "libmodpb64",
- "libosi",
- "libprotobuf-cpp-lite",
- ],
- include_dirs: [
- "packages/modules/Bluetooth/system",
- ],
- header_libs: [
- "libbluetooth_headers",
- ],
- fuzz_config: {
- cc: ["android-bluetooth-security@google.com"],
- componentid: 27441,
- hotlists: [
- "4593311",
- ],
- description: "The fuzzer targets the APIs of libbtcore",
- vector: "local_no_privileges_required",
- service_privilege: "privileged",
- users: "multi_user",
- fuzzed_code_usage: "shipped",
- },
-}
-
-cc_fuzz {
- name: "btcore_device_class_fuzzer",
- defaults: [
- "btcore_fuzz_defaults",
- ],
- srcs: [
- "btcore_device_class_fuzzer.cpp",
- ],
-}
-
-cc_fuzz {
- name: "btcore_property_fuzzer",
- defaults: [
- "btcore_fuzz_defaults",
- ],
- srcs: [
- "btcore_property_fuzzer.cpp",
- ],
-
-}
-
-cc_fuzz {
- name: "btcore_module_fuzzer",
- enabled: false,
- defaults: [
- "btcore_fuzz_defaults",
- ],
- srcs: [
- "btcore_module_fuzzer.cpp",
- ],
-}
diff --git a/system/btcore/fuzzer/README.md b/system/btcore/fuzzer/README.md
deleted file mode 100644
index cf770e4385..0000000000
--- a/system/btcore/fuzzer/README.md
+++ /dev/null
@@ -1,56 +0,0 @@
-# Fuzzers for libbtcore
-
-## Plugin Design Considerations
-The fuzzer plugins for `libbtcore` are designed based on the understanding of the
-source code and tries to achieve the following:
-
-##### Maximize code coverage
-The configuration parameters are not hard-coded, but instead selected based on
-incoming data. This ensures more code paths are reached by the fuzzers.
-
-Fuzzers assigns values to the following parameters to pass on to libbtcore:
-1. Bluetooth Device Type (parameter name: `deviceType`)
-2. Bluetooth Adapter Visibility Mode (parameter name: `mode`)
-3. Bluetooth Address (parameter name: `btAddress`)
-4. Bluetooth Device Class parameter (parameter name: `deviceClassT`)
-
-| Parameter| Valid Values| Configured Value|
-|------------- |-------------| ----- |
-| `deviceType` | 0.`BT_DEVICE_DEVTYPE_BREDR` 1.`BT_DEVICE_DEVTYPE_BLE` 2.`BT_DEVICE_DEVTYPE_DUAL` | Value obtained from FuzzedDataProvider |
-| `mode` | 0.`BT_SCAN_MODE_NONE` 1.`BT_SCAN_MODE_CONNECTABLE` 2.`BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE` | Value obtained from FuzzedDataProvider |
-| `btAddress` | Values inside array ranges from `0x0` to `0xFF` | Value obtained from FuzzedDataProvider |
-| `deviceClassT` | Values inside array ranges from `0x0` to `0xFF` | Value obtained from FuzzedDataProvider |
-This also ensures that the plugins are always deterministic for any given input.
-
-##### Maximize utilization of input data
-The plugins feed the entire input data to the module.
-This ensures that the plugins tolerates any kind of input (empty, huge,
-malformed, etc) and doesn't `exit()` on any input and thereby increasing the
-chance of identifying vulnerabilities.
-
-## Build
-
-This describes steps to build btcore_device_class_fuzzer, btcore_property_fuzzer and btcore_module_fuzzer binaries.
-
-### Android
-
-#### Steps to build
-Build the fuzzer
-```
- $ mm -j$(nproc) btcore_device_class_fuzzer
- $ mm -j$(nproc) btcore_property_fuzzer
- $ mm -j$(nproc) btcore_module_fuzzer
-```
-### Steps to run
-
-To run on device
-```
- $ adb sync data
- $ adb shell /data/fuzz/arm64/btcore_device_class_fuzzer/btcore_device_class_fuzzer
- $ adb shell /data/fuzz/arm64/btcore_property_fuzzer/btcore_property_fuzzer
- $ adb shell /data/fuzz/arm64/btcore_module_fuzzer/btcore_module_fuzzer
-```
-
-## References:
- * http://llvm.org/docs/LibFuzzer.html
- * https://github.com/google/oss-fuzz
diff --git a/system/btcore/fuzzer/btcore_device_class_fuzzer.cpp b/system/btcore/fuzzer/btcore_device_class_fuzzer.cpp
deleted file mode 100644
index fef1e33370..0000000000
--- a/system/btcore/fuzzer/btcore_device_class_fuzzer.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2021 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.
- *
- */
-
-#include <fuzzer/FuzzedDataProvider.h>
-
-#include "btcore/include/device_class.h"
-
-class BTCoreDeviceClassFuzzer {
-public:
- void process(const uint8_t* data, size_t size);
-
-private:
- std::unique_ptr<FuzzedDataProvider> mFdp = nullptr;
-};
-
-void BTCoreDeviceClassFuzzer::process(const uint8_t* data, size_t size) {
- mFdp = std::make_unique<FuzzedDataProvider>(data, size);
- size_t dcStreamSize = sizeof(bt_device_class_t) * sizeof(uint8_t);
-
- std::vector<uint8_t> dcStreamSrc(dcStreamSize, 0x0);
- mFdp->ConsumeData(dcStreamSrc.data(), dcStreamSize);
-
- bt_device_class_t deviceClass;
- device_class_from_stream(&deviceClass, dcStreamSrc.data());
-
- std::vector<uint8_t> dcStreamDst(dcStreamSize, 0x0);
- (void)device_class_to_stream(&deviceClass, dcStreamDst.data(), dcStreamSize);
-
- device_class_set_limited(&deviceClass, mFdp->ConsumeBool());
- (void)device_class_get_limited(&deviceClass);
-
- int val = mFdp->ConsumeIntegral<int>();
- device_class_set_major_device(&deviceClass, val);
- (void)device_class_get_major_device(&deviceClass);
-
- val = mFdp->ConsumeIntegral<int>();
- device_class_set_minor_device(&deviceClass, val);
- (void)device_class_get_minor_device(&deviceClass);
-
- device_class_set_information(&deviceClass, mFdp->ConsumeBool());
- (void)device_class_get_information(&deviceClass);
-
- bt_device_class_t deviceClassCopy;
- (void)device_class_copy(&deviceClassCopy, &deviceClass);
- (void)device_class_equals(&deviceClass, &deviceClassCopy);
-
- val = mFdp->ConsumeIntegralInRange(1, INT_MAX);
- device_class_from_int(&deviceClass, val);
- (void)device_class_to_int(&deviceClass);
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- BTCoreDeviceClassFuzzer btCoreDeviceClassFuzzer;
- btCoreDeviceClassFuzzer.process(data, size);
- return 0;
-}
diff --git a/system/btcore/fuzzer/btcore_module_fuzzer.cpp b/system/btcore/fuzzer/btcore_module_fuzzer.cpp
deleted file mode 100644
index adb21b724d..0000000000
--- a/system/btcore/fuzzer/btcore_module_fuzzer.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2021 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.
- *
- */
-
-#include "btcore/include/hal_util.h"
-#include "btcore/include/module.h"
-
-extern const module_t osi_module;
-
-extern "C" {
-struct android_namespace_t* android_get_exported_namespace(const char*) { return nullptr; }
-}
-
-class BTCoreModuleFuzzer {
-public:
- void process();
-};
-
-void BTCoreModuleFuzzer::process() {
- const bt_interface_t* interface;
- (void)hal_util_load_bt_library(&interface);
- module_management_start();
- module_init(&osi_module);
- (void)module_start_up(&osi_module);
- (void)get_module(osi_module.name);
- module_shut_down(&osi_module);
- module_clean_up(&osi_module);
- module_management_stop();
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t*, size_t) {
- BTCoreModuleFuzzer btCoreModuleFuzzer;
- btCoreModuleFuzzer.process();
- return 0;
-}
diff --git a/system/btcore/fuzzer/btcore_property_fuzzer.cpp b/system/btcore/fuzzer/btcore_property_fuzzer.cpp
deleted file mode 100644
index eabcf505c3..0000000000
--- a/system/btcore/fuzzer/btcore_property_fuzzer.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2021 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.
- *
- */
-
-#include <fuzzer/FuzzedDataProvider.h>
-
-#include "btcore/include/property.h"
-#include "types/bluetooth/uuid.h"
-#include "types/raw_address.h"
-
-using bluetooth::Uuid;
-
-constexpr int32_t kRandomStringLength = 256;
-
-class BTCorePropertyFuzzer {
-public:
- void process(const uint8_t* data, size_t size);
-
-private:
- std::unique_ptr<FuzzedDataProvider> mFdp = nullptr;
-};
-
-void BTCorePropertyFuzzer::process(const uint8_t* data, size_t size) {
- mFdp = std::make_unique<FuzzedDataProvider>(data, size);
- uint8_t addr[RawAddress::kLength];
- mFdp->ConsumeData(addr, sizeof(uint8_t) * RawAddress::kLength);
- RawAddress btAddress = {addr};
- bt_property_t* property = property_new_addr(&btAddress);
- property_as_addr(property);
- property_free(property);
-
- bt_device_class_t deviceClass = {{mFdp->ConsumeIntegral<uint8_t>(),
- mFdp->ConsumeIntegral<uint8_t>(),
- mFdp->ConsumeIntegral<uint8_t>()}};
- property = property_new_device_class(&deviceClass);
-
- const bt_device_class_t* pDeviceClass = property_as_device_class(property);
- (void)device_class_to_int(pDeviceClass);
- property_free(property);
-
- bt_device_type_t deviceType = (bt_device_type_t)(mFdp->ConsumeIntegral<uint32_t>());
- property = property_new_device_type(deviceType);
- (void)property_as_device_type(property);
- property_free(property);
-
- uint32_t timeout = mFdp->ConsumeIntegral<uint32_t>();
- property = property_new_discoverable_timeout(timeout);
- (void)property_as_discoverable_timeout(property);
- property_free(property);
-
- std::string name = mFdp->ConsumeRandomLengthString(kRandomStringLength);
- property = property_new_name(name.c_str());
- (void)property_as_name(property);
- property_free(property);
-
- int8_t rssi = mFdp->ConsumeIntegral<int8_t>();
- property = property_new_rssi(rssi);
- (void)property_as_rssi(property);
- property_free(property);
-
- size_t uuidSize = sizeof(uint8_t) * bluetooth::Uuid::kNumBytes128;
- uint8_t uuid[bluetooth::Uuid::kNumBytes128];
- mFdp->ConsumeData(uuid, uuidSize);
- Uuid uuidBE = Uuid::From128BitBE(uuid);
- property = property_new_uuids(&uuidBE, 1);
- size_t uuidCount;
- (void)property_as_uuids(property, &uuidCount);
- property_free(property);
-
- mFdp->ConsumeData(uuid, uuidSize);
- Uuid uuidLE = Uuid::From128BitLE(uuid);
- Uuid uuids[] = {uuidBE, uuidLE};
- bt_property_t* propertySrc = property_new_uuids(uuids, std::size(uuids));
- bt_property_t propertyDest;
- (void)property_copy(&propertyDest, propertySrc);
- property_free(propertySrc);
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- BTCorePropertyFuzzer btCorePropertyFuzzer;
- btCorePropertyFuzzer.process(data, size);
- return 0;
-}
diff --git a/system/btcore/include/device_class.h b/system/btcore/include/device_class.h
deleted file mode 100644
index 6f56b119b0..0000000000
--- a/system/btcore/include/device_class.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/******************************************************************************
- *
- * Copyright 2014 Google, Inc.
- *
- * 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.
- *
- ******************************************************************************/
-
-#pragma once
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-// Provides Class Of Device primitive as specified in the bluetooth spec.
-// [Class Of Device]
-// (https://www.bluetooth.org/en-us/specification/assigned-numbers/baseband)
-
-// Device class may be defined in other structures.
-// Only use defined methods to manipulate internals.
-typedef struct bt_device_class_t {
- uint8_t _[3]; // Do not access directly; use methods below.
-} bt_device_class_t;
-
-// Copies the |data| class of device stream into device class |dc|. |dc|
-// and |data| must not be NULL.
-void device_class_from_stream(bt_device_class_t* dc, const uint8_t* data);
-
-// Serializes the device class |dc| to pointer argument |data| in big endian
-// format. |len| must contain the buffer size of |data|. Returns the actual
-// number of bytes copied into |data|. |dc| and |data| must not be NULL.
-int device_class_to_stream(const bt_device_class_t* dc, uint8_t* data, size_t len);
-
-// Copies the |data| class of device integer into device class |dc|. |dc|
-// must not be NULL.
-void device_class_from_int(bt_device_class_t* dc, int data);
-
-// Returns the device class |dc| in integer format. |dc| must not be NULL.
-int device_class_to_int(const bt_device_class_t* dc);
-
-// Compares and returns |true| if two device classes |p1| and |p2| are equal.
-// False otherwise.
-bool device_class_equals(const bt_device_class_t* p1, const bt_device_class_t* p2);
-
-// Copies and returns |true| if the device class was successfully copied from
-// |p2| into |p1|. False otherwise.
-bool device_class_copy(bt_device_class_t* dest, const bt_device_class_t* src);
-
-// Query, getters and setters for the major device class. |dc| must not be
-// NULL.
-int device_class_get_major_device(const bt_device_class_t* dc);
-void device_class_set_major_device(bt_device_class_t* dc, int val);
-
-// Query, getters and setters for the minor device class. |dc| must not be NULL.
-int device_class_get_minor_device(const bt_device_class_t* dc);
-void device_class_set_minor_device(bt_device_class_t* dc, int val);
-
-// Query, getters and setters for the various major service class features.
-// |dc| must not be NULL.
-bool device_class_get_limited(const bt_device_class_t* dc);
-void device_class_set_limited(bt_device_class_t* dc, bool set);
-
-bool device_class_get_positioning(const bt_device_class_t* dc);
-void device_class_set_positioning(bt_device_class_t* dc, bool set);
-
-bool device_class_get_networking(const bt_device_class_t* dc);
-void device_class_set_networking(bt_device_class_t* dc, bool set);
-
-bool device_class_get_rendering(const bt_device_class_t* dc);
-void device_class_set_rendering(bt_device_class_t* dc, bool set);
-
-bool device_class_get_capturing(const bt_device_class_t* dc);
-void device_class_set_capturing(bt_device_class_t* dc, bool set);
-
-bool device_class_get_object_transfer(const bt_device_class_t* dc);
-void device_class_set_object_transfer(bt_device_class_t* dc, bool set);
-
-bool device_class_get_audio(const bt_device_class_t* dc);
-void device_class_set_audio(bt_device_class_t* dc, bool set);
-
-bool device_class_get_telephony(const bt_device_class_t* dc);
-void device_class_set_telephony(bt_device_class_t* dc, bool set);
-
-bool device_class_get_information(const bt_device_class_t* dc);
-void device_class_set_information(bt_device_class_t* dc, bool set);
diff --git a/system/btcore/include/device_features.h b/system/btcore/include/device_features.h
deleted file mode 100644
index 13f8653635..0000000000
--- a/system/btcore/include/device_features.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/******************************************************************************
- *
- * Copyright 2014 Google, Inc.
- *
- * 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.
- *
- ******************************************************************************/
-
-#pragma once
-
-#include <stdint.h>
-
-// Represents a page of device feature enabled/disabled bits returned
-// by the local controller. See the bluetooth spec for bit indexes.
-typedef struct {
- uint8_t as_array[8];
-} bt_device_features_t;
diff --git a/system/btcore/include/event_mask.h b/system/btcore/include/event_mask.h
deleted file mode 100644
index f811c78c8e..0000000000
--- a/system/btcore/include/event_mask.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/******************************************************************************
- *
- * Copyright 2014 Google, Inc.
- *
- * 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.
- *
- ******************************************************************************/
-
-#pragma once
-
-#include <stdint.h>
-
-// Represents a mask which can be used to tell the controller which
-// HCI events the stack wishes to be informed about. See the bluetooth
-// spec for more information on what each bit means.
-typedef struct {
- const uint8_t as_array[8];
-} bt_event_mask_t;
diff --git a/system/btcore/include/iac.h b/system/btcore/include/iac.h
deleted file mode 100644
index 39c830e54b..0000000000
--- a/system/btcore/include/iac.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/******************************************************************************
- *
- * Copyright 2014 Google, Inc.
- *
- * 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.
- *
- ******************************************************************************/
-
-#pragma once
-
-#include <stdint.h>
-
-// Inquiry Access Code
-// [Bluetooth Baseband]
-// (https://www.bluetooth.org/en-us/specification/assigned-numbers/baseband)
-typedef struct {
- uint8_t iac[3];
-} __attribute__((packed)) bt_inquiry_access_code_t;
diff --git a/system/btcore/include/property.h b/system/btcore/include/property.h
deleted file mode 100644
index f8e06150ad..0000000000
--- a/system/btcore/include/property.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/******************************************************************************
- *
- * Copyright 2014 Google, Inc.
- *
- * 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.
- *
- ******************************************************************************/
-
-#pragma once
-
-#include <hardware/bluetooth.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#include "btcore/include/device_class.h"
-#include "types/bluetooth/uuid.h"
-#include "types/raw_address.h"
-
-// Copies an array of consecutive properties of |count| to a newly
-// allocated array. |properties| must not be NULL.
-bt_property_t* property_copy_array(const bt_property_t* properties, size_t count);
-
-// Copies |src| to |dest|. Returns the value of |dest|.
-// |src| and |dest| must not be NULL.
-bt_property_t* property_copy(bt_property_t* dest, const bt_property_t* src);
-
-// Returns true if the value of the two properties |p1| and |p2| are equal.
-// |p1| and |p2| must not be NULL.
-bool property_equals(const bt_property_t* p1, const bt_property_t* p2);
-
-// Property resource allocations. Caller is expected to free |property|
-// using |property_free| or |property_free_array|.
-// Parameter must not be NULL. A copy of the parameter is made and
-// stored in the property.
-bt_property_t* property_new_addr(const RawAddress* addr);
-bt_property_t* property_new_device_class(const bt_device_class_t* dc);
-bt_property_t* property_new_device_type(bt_device_type_t device_type);
-bt_property_t* property_new_discoverable_timeout(const uint32_t timeout);
-bt_property_t* property_new_name(const char* name);
-bt_property_t* property_new_rssi(const int8_t rssi);
-bt_property_t* property_new_uuids(const bluetooth::Uuid* uuid, size_t count);
-
-// Property resource frees both property and value.
-void property_free(bt_property_t* property);
-void property_free_array(bt_property_t* properties, size_t count);
-
-// Value check convenience methods. The contents of the property are
-// checked for the respective validity and returns true, false otherwise.
-// |property| must not be NULL.
-bool property_is_addr(const bt_property_t* property);
-bool property_is_device_class(const bt_property_t* property);
-bool property_is_device_type(const bt_property_t* property);
-bool property_is_discoverable_timeout(const bt_property_t* property);
-bool property_is_name(const bt_property_t* property);
-bool property_is_rssi(const bt_property_t* property);
-bool property_is_uuids(const bt_property_t* property);
-
-// Value conversion convenience methods. The contents of the property are
-// properly typed and returned to the caller. |property| must not be NULL.
-const RawAddress* property_as_addr(const bt_property_t* property);
-const bt_device_class_t* property_as_device_class(const bt_property_t* property);
-bt_device_type_t property_as_device_type(const bt_property_t* property);
-uint32_t property_as_discoverable_timeout(const bt_property_t* property);
-const bt_bdname_t* property_as_name(const bt_property_t* property);
-int8_t property_as_rssi(const bt_property_t* property);
-const bluetooth::Uuid* property_as_uuids(const bt_property_t* property, size_t* count);
diff --git a/system/btcore/include/version.h b/system/btcore/include/version.h
deleted file mode 100644
index d7787c7409..0000000000
--- a/system/btcore/include/version.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/******************************************************************************
- *
- * Copyright 2014 Google, Inc.
- *
- * 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.
- *
- ******************************************************************************/
-
-#pragma once
-
-#include <stdint.h>
-
-typedef struct {
- uint8_t hci_version;
- uint16_t hci_revision;
- uint8_t lmp_version;
- uint16_t manufacturer;
- uint16_t lmp_subversion;
-} bt_version_t;
diff --git a/system/btcore/src/device_class.cc b/system/btcore/src/device_class.cc
deleted file mode 100644
index 08d2ae191a..0000000000
--- a/system/btcore/src/device_class.cc
+++ /dev/null
@@ -1,167 +0,0 @@
-/******************************************************************************
- *
- * Copyright 2014 Google, Inc.
- *
- * 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.
- *
- ******************************************************************************/
-
-#include "btcore/include/device_class.h"
-
-#include <arpa/inet.h>
-#include <bluetooth/log.h>
-#include <endian.h>
-#include <string.h>
-
-using namespace bluetooth;
-
-typedef struct _bt_device_class_t {
- uint32_t unused : 2; // LSBs
- uint32_t minor_device : 6;
- uint32_t major_device : 5;
- uint32_t major_service : 11; // MSBs
-} __attribute__((__packed__)) _bt_device_class_t;
-
-// Convenience to interpret raw device class bytes.
-#define DC(x) ((_bt_device_class_t*)(x))
-
-// Ensure the internal device class implementation and public one
-// have equal size.
-static_assert(sizeof(_bt_device_class_t) == sizeof(bt_device_class_t),
- "Internal and external device class implementation should have the same size");
-
-// [Major Service Classes]
-// (https://www.bluetooth.org/en-us/specification/assigned-numbers/baseband)
-enum {
- DC_LIMITED_DISCOVERABLE_MODE = 0x0001,
- DC_RESERVED14 = 0x0002,
- DC_RESERVED15 = 0x0004,
- DC_POSITIONING = 0x0008,
- DC_NETWORKING = 0x0010,
- DC_RENDERING = 0x0020,
- DC_CAPTURING = 0x0040,
- DC_OBJECT_TRANSFER = 0x0080,
- DC_AUDIO = 0x0100,
- DC_TELEPHONY = 0x0200,
- DC_INFORMATION = 0x0400,
-};
-
-static bool device_class_get_major_service_(const bt_device_class_t* dc, int bitmask);
-static void device_class_clr_major_service_(bt_device_class_t* dc, int bitmask);
-static void device_class_set_major_service_(bt_device_class_t* dc, int bitmask);
-
-void device_class_from_stream(bt_device_class_t* dc, const uint8_t* data) {
- log::assert_that(dc != NULL, "assert failed: dc != NULL");
- log::assert_that(data != NULL, "assert failed: data != NULL");
- *dc = *(bt_device_class_t*)data;
-}
-
-int device_class_to_stream(const bt_device_class_t* dc, uint8_t* data, size_t len) {
- log::assert_that(dc != NULL, "assert failed: dc != NULL");
- log::assert_that(data != NULL, "assert failed: data != NULL");
- log::assert_that(len >= sizeof(bt_device_class_t),
- "assert failed: len >= sizeof(bt_device_class_t)");
- for (size_t i = 0; i < sizeof(bt_device_class_t); ++i) {
- data[i] = dc->_[i];
- }
- return sizeof(bt_device_class_t);
-}
-
-void device_class_from_int(bt_device_class_t* dc, int data) {
- log::assert_that(dc != NULL, "assert failed: dc != NULL");
- log::assert_that(data != 0, "assert failed: data != 0");
- // Careful with endianess.
- dc->_[0] = data & 0xff;
- dc->_[1] = (data >> 8) & 0xff;
- dc->_[2] = (data >> 16) & 0xff;
-}
-
-int device_class_to_int(const bt_device_class_t* dc) {
- log::assert_that(dc != NULL, "assert failed: dc != NULL");
- // Careful with endianess.
- int val = 0;
- memcpy(&val, dc, sizeof(*dc));
- return static_cast<int>(le32toh(val) & 0xffffff);
-}
-
-bool device_class_equals(const bt_device_class_t* p1, const bt_device_class_t* p2) {
- log::assert_that(p1 != NULL, "assert failed: p1 != NULL");
- log::assert_that(p2 != NULL, "assert failed: p2 != NULL");
- return memcmp(p1, p2, sizeof(bt_device_class_t)) == 0;
-}
-
-bool device_class_copy(bt_device_class_t* dest, const bt_device_class_t* src) {
- log::assert_that(dest != NULL, "assert failed: dest != NULL");
- log::assert_that(src != NULL, "assert failed: src != NULL");
- return memcpy(dest, src, sizeof(bt_device_class_t)) == dest;
-}
-
-int device_class_get_major_device(const bt_device_class_t* dc) {
- log::assert_that(dc != NULL, "assert failed: dc != NULL");
- return DC(dc)->major_device;
-}
-
-void device_class_set_major_device(bt_device_class_t* dc, int val) {
- log::assert_that(dc != NULL, "assert failed: dc != NULL");
- DC(dc)->major_device = val;
-}
-
-int device_class_get_minor_device(const bt_device_class_t* dc) {
- log::assert_that(dc != NULL, "assert failed: dc != NULL");
- return DC(dc)->minor_device;
-}
-
-void device_class_set_minor_device(bt_device_class_t* dc, int val) {
- log::assert_that(dc != NULL, "assert failed: dc != NULL");
- DC(dc)->minor_device = val;
-}
-
-bool device_class_get_information(const bt_device_class_t* dc) {
- log::assert_that(dc != NULL, "assert failed: dc != NULL");
- return device_class_get_major_service_(dc, DC_INFORMATION);
-}
-
-void device_class_set_information(bt_device_class_t* dc, bool set) {
- log::assert_that(dc != NULL, "assert failed: dc != NULL");
- if (set) {
- device_class_set_major_service_(dc, DC_INFORMATION);
- } else {
- device_class_clr_major_service_(dc, DC_INFORMATION);
- }
-}
-
-bool device_class_get_limited(const bt_device_class_t* dc) {
- log::assert_that(dc != NULL, "assert failed: dc != NULL");
- return device_class_get_major_service_(dc, DC_LIMITED_DISCOVERABLE_MODE);
-}
-
-void device_class_set_limited(bt_device_class_t* dc, bool set) {
- log::assert_that(dc != NULL, "assert failed: dc != NULL");
- if (set) {
- device_class_set_major_service_(dc, DC_LIMITED_DISCOVERABLE_MODE);
- } else {
- device_class_clr_major_service_(dc, DC_LIMITED_DISCOVERABLE_MODE);
- }
-}
-
-static bool device_class_get_major_service_(const bt_device_class_t* dc, int bitmask) {
- return DC(dc)->major_service & bitmask;
-}
-
-static void device_class_clr_major_service_(bt_device_class_t* dc, int bitmask) {
- DC(dc)->major_service &= ~bitmask;
-}
-
-static void device_class_set_major_service_(bt_device_class_t* dc, int bitmask) {
- DC(dc)->major_service |= bitmask;
-}
diff --git a/system/btcore/src/property.cc b/system/btcore/src/property.cc
deleted file mode 100644
index 0379229432..0000000000
--- a/system/btcore/src/property.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-/******************************************************************************
- *
- * Copyright 2014 Google, Inc.
- *
- * 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.
- *
- ******************************************************************************/
-
-#include "btcore/include/property.h"
-
-#include <bluetooth/log.h>
-#include <string.h>
-
-#include "btcore/include/device_class.h"
-#include "osi/include/allocator.h"
-#include "osi/include/compat.h"
-#include "types/bluetooth/uuid.h"
-#include "types/raw_address.h"
-
-using bluetooth::Uuid;
-using namespace bluetooth;
-
-static bt_property_t* property_new_(void* val, size_t len, bt_property_type_t type);
-
-bt_property_t* property_copy_array(const bt_property_t* properties, size_t count) {
- log::assert_that(properties != NULL, "assert failed: properties != NULL");
- bt_property_t* clone = static_cast<bt_property_t*>(osi_calloc(sizeof(bt_property_t) * count));
-
- memcpy(&clone[0], &properties[0], sizeof(bt_property_t) * count);
- for (size_t i = 0; i < count; ++i) {
- clone[i].val = osi_calloc(clone[i].len);
- memcpy(clone[i].val, properties[i].val, clone[i].len);
- }
-
- return clone;
-}
-
-bt_property_t* property_copy(bt_property_t* dest, const bt_property_t* src) {
- log::assert_that(dest != NULL, "assert failed: dest != NULL");
- log::assert_that(src != NULL, "assert failed: src != NULL");
- return (bt_property_t*)memcpy(dest, src, sizeof(bt_property_t));
-}
-
-bool property_equals(const bt_property_t* p1, const bt_property_t* p2) {
- // Two null properties are not the same. May need to revisit that
- // decision when we have a test case that exercises that condition.
- if (!p1 || !p2 || p1->type != p2->type) {
- return false;
- }
-
- // Although the Bluetooth name is a 249-byte array, the implementation
- // treats it like a variable-length array with its size specified in the
- // property's `len` field. We special-case the equivalence of BDNAME
- // types here by truncating the larger, zero-padded name to its string
- // length and comparing against the shorter name.
- //
- // Note: it may be the case that both strings are zero-padded but that
- // hasn't come up yet so this implementation doesn't handle it.
- if (p1->type == BT_PROPERTY_BDNAME && p1->len != p2->len) {
- const bt_property_t *shorter = p1, *longer = p2;
- if (p1->len > p2->len) {
- shorter = p2;
- longer = p1;
- }
- return strlen((const char*)longer->val) == (size_t)shorter->len &&
- !memcmp(longer->val, shorter->val, shorter->len);
- }
-
- return p1->len == p2->len && !memcmp(p1->val, p2->val, p1->len);
-}
-
-bt_property_t* property_new_addr(const RawAddress* addr) {
- log::assert_that(addr != NULL, "assert failed: addr != NULL");
- return property_new_((void*)addr, sizeof(RawAddress), BT_PROPERTY_BDADDR);
-}
-
-bt_property_t* property_new_device_class(const bt_device_class_t* dc) {
- log::assert_that(dc != NULL, "assert failed: dc != NULL");
- return property_new_((void*)dc, sizeof(bt_device_class_t), BT_PROPERTY_CLASS_OF_DEVICE);
-}
-
-bt_property_t* property_new_device_type(bt_device_type_t type) {
- return property_new_((void*)&type, sizeof(bt_device_type_t), BT_PROPERTY_TYPE_OF_DEVICE);
-}
-
-bt_property_t* property_new_discoverable_timeout(const uint32_t timeout) {
- return property_new_((void*)&timeout, sizeof(uint32_t), BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT);
-}
-
-bt_property_t* property_new_name(const char* name) {
- log::assert_that(name != NULL, "assert failed: name != NULL");
- return property_new_((void*)name, sizeof(bt_bdname_t), BT_PROPERTY_BDNAME);
-}
-
-bt_property_t* property_new_rssi(int8_t rssi) {
- return property_new_((void*)&rssi, sizeof(int8_t), BT_PROPERTY_REMOTE_RSSI);
-}
-
-bt_property_t* property_new_uuids(const Uuid* uuid, size_t count) {
- log::assert_that(uuid != NULL, "assert failed: uuid != NULL");
- return property_new_((void*)uuid, sizeof(Uuid) * count, BT_PROPERTY_UUIDS);
-}
-
-void property_free(bt_property_t* property) { property_free_array(property, 1); }
-
-void property_free_array(bt_property_t* properties, size_t count) {
- if (properties == NULL) {
- return;
- }
-
- for (size_t i = 0; i < count; ++i) {
- osi_free(properties[i].val);
- }
-
- osi_free(properties);
-}
-
-bool property_is_addr(const bt_property_t* property) {
- log::assert_that(property != NULL, "assert failed: property != NULL");
- return property->type == BT_PROPERTY_BDADDR;
-}
-
-bool property_is_device_class(const bt_property_t* property) {
- log::assert_that(property != NULL, "assert failed: property != NULL");
- return property->type == BT_PROPERTY_CLASS_OF_DEVICE;
-}
-
-bool property_is_device_type(const bt_property_t* property) {
- log::assert_that(property != NULL, "assert failed: property != NULL");
- return property->type == BT_PROPERTY_TYPE_OF_DEVICE;
-}
-
-bool property_is_discoverable_timeout(const bt_property_t* property) {
- log::assert_that(property != NULL, "assert failed: property != NULL");
- return property->type == BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT;
-}
-
-bool property_is_name(const bt_property_t* property) {
- log::assert_that(property != NULL, "assert failed: property != NULL");
- return property->type == BT_PROPERTY_BDNAME;
-}
-
-bool property_is_rssi(const bt_property_t* property) {
- log::assert_that(property != NULL, "assert failed: property != NULL");
- return property->type == BT_PROPERTY_REMOTE_RSSI;
-}
-
-bool property_is_uuids(const bt_property_t* property) {
- log::assert_that(property != NULL, "assert failed: property != NULL");
- return property->type == BT_PROPERTY_UUIDS;
-}
-
-// Convenience conversion methods to property values
-const RawAddress* property_as_addr(const bt_property_t* property) {
- log::assert_that(property_is_addr(property), "assert failed: property_is_addr(property)");
- return (const RawAddress*)property->val;
-}
-
-const bt_device_class_t* property_as_device_class(const bt_property_t* property) {
- log::assert_that(property_is_device_class(property),
- "assert failed: property_is_device_class(property)");
- return (const bt_device_class_t*)property->val;
-}
-
-bt_device_type_t property_as_device_type(const bt_property_t* property) {
- log::assert_that(property_is_device_type(property),
- "assert failed: property_is_device_type(property)");
- return *(const bt_device_type_t*)property->val;
-}
-
-uint32_t property_as_discoverable_timeout(const bt_property_t* property) {
- log::assert_that(property_is_discoverable_timeout(property),
- "assert failed: property_is_discoverable_timeout(property)");
- return *(const uint32_t*)property->val;
-}
-
-const bt_bdname_t* property_as_name(const bt_property_t* property) {
- log::assert_that(property_is_name(property), "assert failed: property_is_name(property)");
- return (const bt_bdname_t*)property->val;
-}
-
-int8_t property_as_rssi(const bt_property_t* property) {
- log::assert_that(property_is_rssi(property), "assert failed: property_is_rssi(property)");
- return *(const int8_t*)property->val;
-}
-
-const Uuid* property_as_uuids(const bt_property_t* property, size_t* count) {
- log::assert_that(property_is_uuids(property), "assert failed: property_is_uuids(property)");
- *count = sizeof(Uuid) / property->len;
- return (const Uuid*)property->val;
-}
-
-static bt_property_t* property_new_(void* val, size_t len, bt_property_type_t type) {
- bt_property_t* property = static_cast<bt_property_t*>(osi_calloc(sizeof(bt_property_t)));
-
- property->val = osi_calloc(len + 1);
- if (type == BT_PROPERTY_BDNAME) {
- osi_strlcpy((char*)property->val, (const char*)val, len);
- } else {
- memcpy(property->val, val, len);
- }
-
- property->type = type;
- property->len = len;
-
- return property;
-}
diff --git a/system/btcore/test/device_class_test.cc b/system/btcore/test/device_class_test.cc
deleted file mode 100644
index ed5f9581f0..0000000000
--- a/system/btcore/test/device_class_test.cc
+++ /dev/null
@@ -1,224 +0,0 @@
-/******************************************************************************
- *
- * Copyright 2014 Google, Inc.
- *
- * 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.
- *
- ******************************************************************************/
-
-#include "btcore/include/device_class.h"
-
-#include <arpa/inet.h>
-#include <gtest/gtest.h>
-
-static ::testing::AssertionResult check_bitfield(const char* m_expr, const char* n_expr, int m,
- int n) {
- if (m == n) {
- return ::testing::AssertionSuccess();
- }
-
- std::stringstream ss;
-
- ss.str("");
- ss << std::showbase << std::hex << std::setw(8) << std::setfill('0') << m;
- std::string expected_str = ss.str();
-
- ss.str("");
- ss << std::showbase << std::hex << std::setw(8) << std::setfill('0') << n;
- std::string actual_str = ss.str();
-
- return ::testing::AssertionFailure()
- << m_expr << " and " << n_expr << " ( " << expected_str << " vs " << actual_str << " )";
-}
-
-class DeviceClassTest : public ::testing::Test {};
-
-TEST_F(DeviceClassTest, cod_sizeof) {
- uint8_t dc_stream[] = {0x00, 0x00, 0x00, 0x00};
- bt_device_class_t dc0;
- device_class_from_stream(&dc0, dc_stream);
- EXPECT_EQ((size_t)3, sizeof(dc0));
-}
-
-TEST_F(DeviceClassTest, simple) {
- uint8_t dc_stream[][sizeof(bt_device_class_t)] = {
- {0x00, 0x00, 0x00}, {0xff, 0xff, 0xff}, {0xaa, 0x55, 0xaa},
- {0x01, 0x23, 0x45}, {0x20, 0x07, 0x14},
- };
-
- for (size_t i = 0; i < sizeof(dc_stream) / sizeof(bt_device_class_t); i++) {
- bt_device_class_t dc;
- device_class_from_stream(&dc, (uint8_t*)&dc_stream[i]);
-
- uint8_t* to_stream = (uint8_t*)&dc;
- EXPECT_PRED_FORMAT2(check_bitfield, (unsigned)dc_stream[i][0], to_stream[0]);
- EXPECT_PRED_FORMAT2(check_bitfield, (unsigned)dc_stream[i][1], to_stream[1]);
- EXPECT_PRED_FORMAT2(check_bitfield, (unsigned)dc_stream[i][2], to_stream[2]);
- }
-}
-
-TEST_F(DeviceClassTest, to_stream) {
- {
- bt_device_class_t dc;
-
- uint8_t dc_stream0[] = {0x00, 0x00, 0x00, 0xaa};
- device_class_from_stream(&dc, dc_stream0);
-
- uint8_t dc_stream1[] = {0x00, 0x00, 0x00, 0x00};
- int rc = device_class_to_stream(&dc, dc_stream1, sizeof(dc_stream1));
- EXPECT_EQ(3, rc);
-
- uint32_t val = 0;
- memcpy(&val, &dc, sizeof(dc));
- EXPECT_PRED_FORMAT2(check_bitfield, 0x00000000, val);
-
- EXPECT_PRED_FORMAT2(check_bitfield, 0x00, dc_stream1[0]);
- EXPECT_PRED_FORMAT2(check_bitfield, 0x00, dc_stream1[1]);
- EXPECT_PRED_FORMAT2(check_bitfield, 0x00, dc_stream1[2]);
- }
-
- {
- uint8_t dc_stream0[] = {0xaa, 0x55, 0xaa, 0x55};
- uint8_t dc_stream1[] = {0x00, 0x00, 0x00, 0x00};
-
- bt_device_class_t dc;
- device_class_from_stream(&dc, dc_stream0);
-
- int rc = device_class_to_stream(&dc, dc_stream1, sizeof(dc_stream1));
- EXPECT_EQ(3, rc);
- uint32_t val = 0;
- memcpy(&val, &dc, sizeof(dc));
- EXPECT_PRED_FORMAT2(check_bitfield, 0x00aa55aa, val);
-
- EXPECT_PRED_FORMAT2(check_bitfield, 0xaa, dc_stream1[0]);
- EXPECT_PRED_FORMAT2(check_bitfield, 0x55, dc_stream1[1]);
- EXPECT_PRED_FORMAT2(check_bitfield, 0xaa, dc_stream1[2]);
- }
-
- {
- uint8_t dc_stream0[] = {0x01, 0x23, 0x45, 0x67};
- uint8_t dc_stream1[] = {0x00, 0x00, 0x00, 0x00};
-
- bt_device_class_t dc;
- device_class_from_stream(&dc, dc_stream0);
-
- int rc = device_class_to_stream(&dc, dc_stream1, sizeof(dc_stream1));
- EXPECT_EQ(3, rc);
- uint32_t val = 0;
- memcpy(&val, &dc, sizeof(dc));
- EXPECT_PRED_FORMAT2(check_bitfield, 0x452301, val);
-
- EXPECT_PRED_FORMAT2(check_bitfield, 0x01, dc_stream1[0]);
- EXPECT_PRED_FORMAT2(check_bitfield, 0x23, dc_stream1[1]);
- EXPECT_PRED_FORMAT2(check_bitfield, 0x45, dc_stream1[2]);
- }
-}
-
-TEST_F(DeviceClassTest, limited_discoverable_mode) {
- uint8_t dc_stream[] = {0x00, 0x00, 0x00};
- bt_device_class_t dc;
- device_class_from_stream(&dc, dc_stream);
- uint32_t test = 0;
- memcpy(&test, &dc, sizeof(dc));
-
- EXPECT_FALSE(device_class_get_limited(&dc));
- EXPECT_EQ((unsigned)0x00000000, test);
-
- device_class_set_limited(&dc, true);
- test = 0;
- memcpy(&test, &dc, sizeof(dc));
- EXPECT_TRUE(device_class_get_limited(&dc));
- EXPECT_EQ((unsigned)0x00002000, test);
-
- device_class_set_limited(&dc, false);
- test = 0;
- memcpy(&test, &dc, sizeof(dc));
- EXPECT_FALSE(device_class_get_limited(&dc));
- EXPECT_EQ((unsigned)0x00000000, test);
-
- device_class_set_limited(&dc, true);
- test = 0;
- memcpy(&test, &dc, sizeof(dc));
- EXPECT_PRED_FORMAT2(check_bitfield, 0x00002000, test);
-
- device_class_set_limited(&dc, false);
- test = 0;
- memcpy(&test, &dc, sizeof(dc));
- EXPECT_PRED_FORMAT2(check_bitfield, 0x00000000, test);
-}
-
-TEST_F(DeviceClassTest, equals) {
- uint8_t dc_stream0[] = {0x00, 0x01, 0x02};
- uint8_t dc_stream1[] = {0x00, 0x02, 0x03};
-
- bt_device_class_t dc0;
- device_class_from_stream(&dc0, dc_stream0);
- bt_device_class_t dc1;
- device_class_from_stream(&dc1, dc_stream1);
- EXPECT_FALSE(device_class_equals(&dc0, &dc1));
-}
-
-TEST_F(DeviceClassTest, copy) {
- uint8_t dc_stream0[] = {0xaa, 0x55, 0x33};
- bt_device_class_t dc0;
- device_class_from_stream(&dc0, dc_stream0);
- bt_device_class_t dc1;
- EXPECT_TRUE(device_class_copy(&dc1, &dc0));
- EXPECT_TRUE(device_class_equals(&dc0, &dc1));
-}
-
-TEST_F(DeviceClassTest, from_int) {
- bt_device_class_t dc1;
- int cod1 = 0x5a020c; // 5898764
- device_class_from_int(&dc1, cod1);
-
- uint8_t dc_stream[] = {0x0c, 0x02, 0x5a};
- bt_device_class_t dc2;
- device_class_from_stream(&dc2, dc_stream);
- EXPECT_TRUE(device_class_equals(&dc1, &dc2));
-}
-
-TEST_F(DeviceClassTest, to_int) {
- bt_device_class_t dc1 = {{0x0c, 0x02, 0x5a}};
- int cod1 = device_class_to_int(&dc1);
-
- EXPECT_EQ(dc1._[0], 0x0c);
- EXPECT_EQ(dc1._[1], 0x02);
- EXPECT_EQ(dc1._[2], 0x5a);
-
- bt_device_class_t dc2;
- uint8_t dc_stream[] = {0x0c, 0x02, 0x5a};
- device_class_from_stream(&dc2, dc_stream);
-
- EXPECT_EQ(dc2._[0], 0x0c);
- EXPECT_EQ(dc2._[1], 0x02);
- EXPECT_EQ(dc2._[2], 0x5a);
-
- int cod2 = device_class_to_int(&dc2);
- EXPECT_EQ(cod1, cod2);
- EXPECT_EQ(cod1, 0x5a020c); // 5898764
-}
-
-TEST_F(DeviceClassTest, endian) {
- bt_device_class_t dc;
- int cod1 = 0x200714; // 2098964
- device_class_from_int(&dc, cod1);
-
- EXPECT_EQ(dc._[0], 0x14);
- EXPECT_EQ(dc._[1], 0x07);
- EXPECT_EQ(dc._[2], 0x20);
-
- int cod2 = device_class_to_int(&dc);
- EXPECT_EQ(cod1, cod2);
- EXPECT_EQ(cod2, 0x200714); // 2098964
-}
diff --git a/system/btcore/test/property_test.cc b/system/btcore/test/property_test.cc
deleted file mode 100644
index 7477bca1a9..0000000000
--- a/system/btcore/test/property_test.cc
+++ /dev/null
@@ -1,269 +0,0 @@
-/******************************************************************************
- *
- * Copyright 2014 Google, Inc.
- *
- * 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.
- *
- ******************************************************************************/
-
-#include "btcore/include/property.h"
-
-#include <arpa/inet.h>
-#include <gtest/gtest.h>
-
-#include "types/bluetooth/uuid.h"
-#include "types/raw_address.h"
-
-using bluetooth::Uuid;
-
-class PropertyTest : public ::testing::Test {};
-
-TEST_F(PropertyTest, addr) {
- RawAddress addr0 = {{0x1, 0x2, 0x3, 0x4, 0x5, 0x6}};
- bt_property_t* property = property_new_addr(&addr0);
-
- EXPECT_EQ(addr0.address[0], ((uint8_t*)property->val)[0]);
- EXPECT_EQ(addr0.address[1], ((uint8_t*)property->val)[1]);
- EXPECT_EQ(addr0.address[2], ((uint8_t*)property->val)[2]);
- EXPECT_EQ(addr0.address[3], ((uint8_t*)property->val)[3]);
- EXPECT_EQ(addr0.address[4], ((uint8_t*)property->val)[4]);
- EXPECT_EQ(addr0.address[5], ((uint8_t*)property->val)[5]);
- EXPECT_EQ(BT_PROPERTY_BDADDR, property->type);
- EXPECT_EQ((int)sizeof(RawAddress), property->len);
-
- const RawAddress* addr1 = property_as_addr(property);
- EXPECT_EQ(addr0.address[0], addr1->address[0]);
-
- property_free(property);
-}
-
-TEST_F(PropertyTest, device_class) {
- bt_device_class_t dc0 = {{0x01, 0x23, 0x45}};
- bt_property_t* property = property_new_device_class(&dc0);
-
- EXPECT_EQ(dc0._[0], ((uint8_t*)property->val)[0]);
- EXPECT_EQ(dc0._[1], ((uint8_t*)property->val)[1]);
- EXPECT_EQ(dc0._[2], ((uint8_t*)property->val)[2]);
- EXPECT_EQ(BT_PROPERTY_CLASS_OF_DEVICE, property->type);
- EXPECT_EQ((int)sizeof(bt_device_class_t), property->len);
-
- const bt_device_class_t* dc1 = property_as_device_class(property);
- int dc_int = device_class_to_int(dc1);
- EXPECT_EQ(0x452301, dc_int);
-
- property_free(property);
-}
-
-TEST_F(PropertyTest, device_type) {
- bt_device_type_t dt0 = (bt_device_type_t)1;
- bt_property_t* property = property_new_device_type(dt0);
-
- EXPECT_EQ((int)dt0, *(int*)property->val);
- EXPECT_EQ(BT_PROPERTY_TYPE_OF_DEVICE, property->type);
- EXPECT_EQ((int)sizeof(bt_device_type_t), property->len);
-
- bt_device_type_t dt1 = property_as_device_type(property);
- EXPECT_EQ(1, (int)dt1);
-
- property_free(property);
-}
-
-TEST_F(PropertyTest, discovery_timeout) {
- uint32_t timeout0 = 12345;
- bt_property_t* property = property_new_discoverable_timeout(timeout0);
-
- EXPECT_EQ(timeout0, *(uint32_t*)property->val);
- EXPECT_EQ(BT_PROPERTY_ADAPTER_DISCOVERABLE_TIMEOUT, property->type);
- EXPECT_EQ((int)sizeof(uint32_t), property->len);
-
- uint32_t timeout1 = property_as_discoverable_timeout(property);
- EXPECT_EQ(timeout0, timeout1);
-
- property_free(property);
-}
-
-TEST_F(PropertyTest, name) {
- const char* name0 = "My btcore name";
- bt_property_t* property = property_new_name(name0);
-
- EXPECT_EQ(0, strcmp((char*)name0, (char*)property->val));
- EXPECT_EQ(BT_PROPERTY_BDNAME, property->type);
- EXPECT_EQ((int)sizeof(bt_bdname_t), property->len);
-
- const bt_bdname_t* name1 = property_as_name(property);
- EXPECT_EQ(0, strcmp((char*)name0, (char*)name1->name));
-
- property_free(property);
-}
-
-TEST_F(PropertyTest, rssi) {
- int8_t rssi0 = -56;
- bt_property_t* property = property_new_rssi(rssi0);
-
- EXPECT_EQ(*(int8_t*)property->val, rssi0);
- EXPECT_EQ(BT_PROPERTY_REMOTE_RSSI, property->type);
- EXPECT_EQ((int)sizeof(int8_t), property->len);
-
- int8_t rss1 = property_as_rssi(property);
- EXPECT_EQ(rssi0, rss1);
-
- property_free(property);
-}
-
-TEST_F(PropertyTest, uuids) {
- Uuid uuid0 = Uuid::From128BitBE({{
- 0x00,
- 0x11,
- 0x22,
- 0x33,
- 0x44,
- 0x55,
- 0x66,
- 0x77,
- 0x88,
- 0x99,
- 0xaa,
- 0xbb,
- 0xcc,
- 0xdd,
- 0xee,
- 0xff,
- }});
- bt_property_t* property = property_new_uuids(&uuid0, 1);
-
- EXPECT_EQ(0, memcmp(uuid0.To128BitBE().data(), property->val, sizeof(Uuid)));
- EXPECT_EQ(BT_PROPERTY_UUIDS, property->type);
- EXPECT_EQ((int)sizeof(Uuid), property->len);
-
- size_t uuid_cnt1;
- const Uuid* uuid1 = property_as_uuids(property, &uuid_cnt1);
- EXPECT_EQ(uuid0, *uuid1);
-
- property_free(property);
-}
-
-TEST_F(PropertyTest, copy) {
- {
- Uuid uuids[] = {
- Uuid::From128BitBE({{
- 0x00,
- 0x11,
- 0x22,
- 0x33,
- 0x44,
- 0x55,
- 0x66,
- 0x77,
- 0x88,
- 0x99,
- 0xaa,
- 0xbb,
- 0xcc,
- 0xdd,
- 0xee,
- 0xff,
- }}),
- Uuid::From128BitBE({{
- 0xf0,
- 0xe1,
- 0xd2,
- 0xc3,
- 0xf4,
- 0xe5,
- 0xd6,
- 0xc7,
- 0xf8,
- 0xe9,
- 0xda,
- 0xcb,
- 0xfc,
- 0xed,
- 0xde,
- 0xcf,
- }}),
- };
-
- bt_property_t* property0 = property_new_uuids(uuids, sizeof(uuids) / sizeof(Uuid));
-
- bt_property_t property1;
- property_copy(&property1, property0);
- EXPECT_TRUE(property_equals(property0, &property1));
-
- property_free(property0);
- }
-}
-
-TEST_F(PropertyTest, equals) {
- {
- RawAddress addr0 = {{0x1, 0x2, 0x3, 0x4, 0x5, 0x6}};
- bt_property_t* property0 = property_new_addr(&addr0);
-
- bt_device_class_t dc0 = {{0x01, 0x23, 0x45}};
- bt_property_t* property1 = property_new_device_class(&dc0);
-
- EXPECT_FALSE(property_equals(property0, property1));
-
- property_free(property0);
- property_free(property1);
- }
-
- {
- RawAddress addr = {{0x1, 0x2, 0x3, 0x4, 0x5, 0x6}};
- bt_property_t* property0 = property_new_addr(&addr);
- bt_property_t* property1 = property_new_addr(&addr);
-
- EXPECT_TRUE(property_equals(property0, property1));
-
- property_free(property0);
- property_free(property1);
- }
-
- {
- RawAddress addr0 = {{0x1, 0x2, 0x3, 0x4, 0x5, 0x6}};
- bt_property_t* property0 = property_new_addr(&addr0);
-
- RawAddress addr1 = {{0x1, 0x2, 0x3, 0x4, 0x5, 0xff}};
- bt_property_t* property1 = property_new_addr(&addr1);
-
- EXPECT_FALSE(property_equals(property0, property1));
-
- property_free(property0);
- property_free(property1);
- }
-
- {
- const char* name0 = "My btcore name";
- bt_property_t* property0 = property_new_name(name0);
-
- const char* name1 = "My btcore name";
- bt_property_t* property1 = property_new_name(name1);
-
- EXPECT_TRUE(property_equals(property0, property1));
-
- property_free(property0);
- property_free(property1);
- }
-
- {
- const char* name0 = "My btcore name";
- bt_property_t* property0 = property_new_name(name0);
-
- const char* name1 = "My btcore name ";
- bt_property_t* property1 = property_new_name(name1);
-
- EXPECT_FALSE(property_equals(property0, property1));
-
- property_free(property0);
- property_free(property1);
- }
-}
diff --git a/system/btif/Android.bp b/system/btif/Android.bp
index 0eb097dca7..82544f36ba 100644
--- a/system/btif/Android.bp
+++ b/system/btif/Android.bp
@@ -122,7 +122,6 @@ cc_library_static {
"src/btif_keystore.cc",
"src/btif_le_audio.cc",
"src/btif_le_audio_broadcaster.cc",
- "src/btif_metrics_logging.cc",
"src/btif_pan.cc",
"src/btif_profile_queue.cc",
"src/btif_profile_queue.cc",
diff --git a/system/btif/BUILD.gn b/system/btif/BUILD.gn
index ea6a0f6fbc..9def60989b 100644
--- a/system/btif/BUILD.gn
+++ b/system/btif/BUILD.gn
@@ -64,7 +64,6 @@ static_library("btif") {
"src/btif_jni_task.cc",
"src/btif_keystore.cc",
"src/btif_le_audio.cc",
- "src/btif_metrics_logging.cc",
"src/btif_pan.cc",
"src/btif_profile_queue.cc",
"src/btif_profile_storage.cc",
diff --git a/system/btif/include/btif_metrics_logging.h b/system/btif/include/btif_metrics_logging.h
deleted file mode 100644
index 94f7a66b79..0000000000
--- a/system/btif/include/btif_metrics_logging.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2021 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.
- */
-
-#pragma once
-
-#include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
-#include <frameworks/proto_logging/stats/enums/bluetooth/hci/enums.pb.h>
-
-#include "main/shim/metric_id_api.h"
-#include "types/raw_address.h"
-
-void log_a2dp_audio_underrun_event(const RawAddress& address, uint64_t encoding_interval_millis,
- int num_missing_pcm_bytes);
-
-void log_a2dp_audio_overrun_event(const RawAddress& address, uint64_t encoding_interval_millis,
- int num_dropped_buffers, int num_dropped_encoded_frames,
- int num_dropped_encoded_bytes);
-
-void log_a2dp_playback_event(const RawAddress& address, int playback_state, int audio_coding_mode);
-
-void log_a2dp_session_metrics_event(const RawAddress& address, int64_t audio_duration_ms,
- int media_timer_min_ms, int media_timer_max_ms,
- int media_timer_avg_ms, int total_scheduling_count,
- int buffer_overruns_max_count, int buffer_overruns_total,
- float buffer_underruns_average, int buffer_underruns_count,
- int64_t codec_index, bool is_a2dp_offload);
-
-void log_read_rssi_result(const RawAddress& address, uint16_t handle, uint32_t cmd_status,
- int8_t rssi);
-
-void log_read_failed_contact_counter_result(const RawAddress& address, uint16_t handle,
- uint32_t cmd_status, int32_t failed_contact_counter);
-
-void log_read_tx_power_level_result(const RawAddress& address, uint16_t handle, uint32_t cmd_status,
- int32_t transmit_power_level);
-
-void log_counter_metrics_btif(android::bluetooth::CodePathCounterKeyEnum key, int64_t value);
-
-void log_socket_connection_state(const RawAddress& address, int port, int type,
- android::bluetooth::SocketConnectionstateEnum connection_state,
- int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port,
- android::bluetooth::SocketRoleEnum socket_role,
- uint64_t connection_duration_ms,
- android::bluetooth::SocketErrorEnum error_code,
- bool is_hardware_offload);
-
-bool init_metric_id_allocator(const std::unordered_map<RawAddress, int>& paired_device_map,
- bluetooth::shim::CallbackLegacy save_id_callback,
- bluetooth::shim::CallbackLegacy forget_device_callback);
-
-bool close_metric_id_allocator();
-
-int allocate_metric_id_from_metric_id_allocator(const RawAddress&);
-
-int save_metric_id_from_metric_id_allocator(const RawAddress&);
-
-void forget_device_from_metric_id_allocator(const RawAddress&);
-
-bool is_valid_id_from_metric_id_allocator(const int id);
diff --git a/system/btif/src/OWNERS b/system/btif/src/OWNERS
deleted file mode 100644
index e495e167d4..0000000000
--- a/system/btif/src/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-per-file btif_hearing_aid.cc=file:/OWNERS_hearingaid
diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc
index 5741b05c4f..9badbc9ab6 100644
--- a/system/btif/src/bluetooth.cc
+++ b/system/btif/src/bluetooth.cc
@@ -71,7 +71,6 @@
#include "btif/include/btif_hh.h"
#include "btif/include/btif_keystore.h"
#include "btif/include/btif_le_audio.h"
-#include "btif/include/btif_metrics_logging.h"
#include "btif/include/btif_pan.h"
#include "btif/include/btif_profile_storage.h"
#include "btif/include/btif_rc.h"
@@ -99,6 +98,7 @@
#include "hardware/bt_vc.h"
#include "internal_include/bt_target.h"
#include "main/shim/dumpsys.h"
+#include "main/shim/metric_id_api.h"
#include "os/parameter_provider.h"
#include "osi/include/alarm.h"
#include "osi/include/allocator.h"
@@ -1099,7 +1099,7 @@ static std::string obfuscate_address(const RawAddress& address) {
}
static int get_metric_id(const RawAddress& address) {
- return allocate_metric_id_from_metric_id_allocator(address);
+ return bluetooth::shim::AllocateIdFromMetricIdAllocator(address);
}
static int set_dynamic_audio_buffer_size(int codec, int size) {
diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc
index bf4c00c0d5..5bf2ef0d87 100644
--- a/system/btif/src/btif_a2dp_source.cc
+++ b/system/btif/src/btif_a2dp_source.cc
@@ -46,13 +46,12 @@
#include "btif_av_co.h"
#include "btif_common.h"
#include "btif_hf.h"
-#include "btif_metrics_logging.h"
#include "btm_iso_api.h"
#include "common/message_loop_thread.h"
-#include "common/metrics.h"
#include "common/repeating_timer.h"
#include "common/time_util.h"
#include "hardware/bt_av.h"
+#include "main/shim/metrics_api.h"
#include "osi/include/allocator.h"
#include "osi/include/fixed_queue.h"
#include "osi/include/wakelock.h"
@@ -931,8 +930,9 @@ static uint32_t btif_a2dp_source_read_callback(uint8_t* p_buf, uint32_t len) {
btif_a2dp_source_cb.stats.media_read_total_underflow_count++;
btif_a2dp_source_cb.stats.media_read_last_underflow_us =
bluetooth::common::time_get_os_boottime_us();
- log_a2dp_audio_underrun_event(btif_av_source_active_peer(),
- btif_a2dp_source_cb.encoder_interval_ms, len - bytes_read);
+ bluetooth::shim::LogMetricA2dpAudioUnderrunEvent(btif_av_source_active_peer(),
+ btif_a2dp_source_cb.encoder_interval_ms,
+ len - bytes_read);
}
return bytes_read;
@@ -984,9 +984,9 @@ static bool btif_a2dp_source_enqueue_callback(BT_HDR* p_buf, size_t frames_n,
osi_free(p_data);
}
}
- log_a2dp_audio_overrun_event(btif_av_source_active_peer(),
- btif_a2dp_source_cb.encoder_interval_ms, drop_n,
- num_dropped_encoded_frames, num_dropped_encoded_bytes);
+ bluetooth::shim::LogMetricA2dpAudioOverrunEvent(
+ btif_av_source_active_peer(), btif_a2dp_source_cb.encoder_interval_ms, drop_n,
+ num_dropped_encoded_frames, num_dropped_encoded_bytes);
// Request additional debug info if we had to flush buffers
RawAddress peer_bda = btif_av_source_active_peer();
@@ -1276,12 +1276,12 @@ static void btif_a2dp_source_update_metrics(void) {
}
if (metrics.audio_duration_ms != -1) {
- log_a2dp_session_metrics_event(btif_av_source_active_peer(), metrics.audio_duration_ms,
- metrics.media_timer_min_ms, metrics.media_timer_max_ms,
- metrics.media_timer_avg_ms, metrics.total_scheduling_count,
- metrics.buffer_overruns_max_count, metrics.buffer_overruns_total,
- metrics.buffer_underruns_average, metrics.buffer_underruns_count,
- metrics.codec_index, metrics.is_a2dp_offload);
+ bluetooth::shim::LogMetricA2dpSessionMetricsEvent(
+ btif_av_source_active_peer(), metrics.audio_duration_ms, metrics.media_timer_min_ms,
+ metrics.media_timer_max_ms, metrics.media_timer_avg_ms, metrics.total_scheduling_count,
+ metrics.buffer_overruns_max_count, metrics.buffer_overruns_total,
+ metrics.buffer_underruns_average, metrics.buffer_underruns_count, metrics.codec_index,
+ metrics.is_a2dp_offload);
}
}
@@ -1301,8 +1301,8 @@ static void btm_read_rssi_cb(void* data) {
return;
}
- log_read_rssi_result(result->rem_bda, bluetooth::common::kUnknownConnectionHandle,
- result->hci_status, result->rssi);
+ bluetooth::shim::LogMetricReadRssiResult(result->rem_bda, bluetooth::os::kUnknownConnectionHandle,
+ result->hci_status, result->rssi);
log::warn("device: {}, rssi: {}", result->rem_bda, result->rssi);
}
@@ -1318,9 +1318,9 @@ static void btm_read_failed_contact_counter_cb(void* data) {
log::error("unable to read Failed Contact Counter (status {})", result->status);
return;
}
- log_read_failed_contact_counter_result(result->rem_bda,
- bluetooth::common::kUnknownConnectionHandle,
- result->hci_status, result->failed_contact_counter);
+ bluetooth::shim::LogMetricReadFailedContactCounterResult(
+ result->rem_bda, bluetooth::os::kUnknownConnectionHandle, result->hci_status,
+ result->failed_contact_counter);
log::warn("device: {}, Failed Contact Counter: {}", result->rem_bda,
result->failed_contact_counter);
@@ -1337,8 +1337,9 @@ static void btm_read_tx_power_cb(void* data) {
log::error("unable to read Tx Power (status {})", result->status);
return;
}
- log_read_tx_power_level_result(result->rem_bda, bluetooth::common::kUnknownConnectionHandle,
- result->hci_status, result->tx_power);
+ bluetooth::shim::LogMetricReadTxPowerLevelResult(result->rem_bda,
+ bluetooth::os::kUnknownConnectionHandle,
+ result->hci_status, result->tx_power);
log::warn("device: {}, Tx Power: {}", result->rem_bda, result->tx_power);
}
diff --git a/system/btif/src/btif_av.cc b/system/btif/src/btif_av.cc
index 101ebcc4a0..2ee3be4c88 100644
--- a/system/btif/src/btif_av.cc
+++ b/system/btif/src/btif_av.cc
@@ -52,18 +52,17 @@
#include "btif/include/btif_a2dp_source.h"
#include "btif/include/btif_av_co.h"
#include "btif/include/btif_common.h"
-#include "btif/include/btif_metrics_logging.h"
#include "btif/include/btif_profile_queue.h"
#include "btif/include/btif_rc.h"
#include "btif/include/btif_util.h"
#include "btif/include/stack_manager_t.h"
-#include "btif_metrics_logging.h"
#include "common/state_machine.h"
#include "device/include/device_iot_conf_defs.h"
#include "device/include/device_iot_config.h"
#include "hardware/bluetooth.h"
#include "hardware/bt_av.h"
#include "include/hardware/bt_rc.h"
+#include "main/shim/metrics_api.h"
#include "osi/include/alarm.h"
#include "osi/include/allocator.h"
#include "osi/include/properties.h"
@@ -1985,7 +1984,7 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event, void* p_data
// incoming/outgoing connect/disconnect requests.
log::warn("Peer {} : event={}: transitioning to Idle due to ACL Disconnect",
peer_.PeerAddress(), BtifAvEvent::EventName(event));
- log_counter_metrics_btif(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::A2DP_CONNECTION_ACL_DISCONNECTED, 1);
btif_report_connection_state(peer_.PeerAddress(), BTAV_CONNECTION_STATE_DISCONNECTED,
bt_status_t::BT_STATUS_FAIL, BTA_AV_FAIL,
@@ -1998,7 +1997,7 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event, void* p_data
case BTA_AV_REJECT_EVT:
log::warn("Peer {} : event={} flags={}", peer_.PeerAddress(), BtifAvEvent::EventName(event),
peer_.FlagsToString());
- log_counter_metrics_btif(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::A2DP_CONNECTION_REJECT_EVT, 1);
btif_report_connection_state(peer_.PeerAddress(), BTAV_CONNECTION_STATE_DISCONNECTED,
bt_status_t::BT_STATUS_AUTH_REJECTED, BTA_AV_FAIL,
@@ -2080,7 +2079,7 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event, void* p_data
btif_report_connection_state(peer_.PeerAddress(), BTAV_CONNECTION_STATE_CONNECTED,
bt_status_t::BT_STATUS_SUCCESS, BTA_AV_SUCCESS,
peer_.IsSource() ? A2dpType::kSink : A2dpType::kSource);
- log_counter_metrics_btif(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::A2DP_CONNECTION_SUCCESS, 1);
} else {
if (btif_rc_is_connected_peer(peer_.PeerAddress())) {
@@ -2099,7 +2098,7 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event, void* p_data
btif_report_connection_state(peer_.PeerAddress(), BTAV_CONNECTION_STATE_DISCONNECTED,
bt_status_t::BT_STATUS_FAIL, status,
peer_.IsSource() ? A2dpType::kSink : A2dpType::kSource);
- log_counter_metrics_btif(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::A2DP_CONNECTION_FAILURE, 1);
}
@@ -2139,8 +2138,8 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event, void* p_data
"Peer {} : event={} : device is already connecting, ignore Connect "
"request",
peer_.PeerAddress(), BtifAvEvent::EventName(event));
- log_counter_metrics_btif(android::bluetooth::CodePathCounterKeyEnum::A2DP_ALREADY_CONNECTING,
- 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::A2DP_ALREADY_CONNECTING, 1);
btif_queue_advance();
} break;
@@ -2151,15 +2150,15 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event, void* p_data
"Peer {} : event={} : device is already connecting, ignore incoming "
"request",
peer_.PeerAddress(), BtifAvEvent::EventName(event));
- log_counter_metrics_btif(android::bluetooth::CodePathCounterKeyEnum::A2DP_ALREADY_CONNECTING,
- 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::A2DP_ALREADY_CONNECTING, 1);
} break;
case BTIF_AV_OFFLOAD_START_REQ_EVT:
log::error("Peer {} : event={}: stream is not Opened", peer_.PeerAddress(),
BtifAvEvent::EventName(event));
btif_a2dp_on_offload_started(peer_.PeerAddress(), BTA_AV_FAIL);
- log_counter_metrics_btif(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::A2DP_OFFLOAD_START_REQ_FAILURE, 1);
break;
@@ -2169,8 +2168,8 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event, void* p_data
bt_status_t::BT_STATUS_FAIL, BTA_AV_FAIL,
peer_.IsSource() ? A2dpType::kSink : A2dpType::kSource);
peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
- log_counter_metrics_btif(android::bluetooth::CodePathCounterKeyEnum::A2DP_CONNECTION_CLOSE,
- 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::A2DP_CONNECTION_CLOSE, 1);
DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(peer_.PeerAddress(), IOT_CONF_KEY_A2DP_CONN_FAIL_COUNT);
if (peer_.SelfInitiatedConnection()) {
btif_queue_advance();
@@ -2184,7 +2183,7 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event, void* p_data
peer_.IsSource() ? A2dpType::kSink : A2dpType::kSource);
peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle);
DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(peer_.PeerAddress(), IOT_CONF_KEY_A2DP_CONN_FAIL_COUNT);
- log_counter_metrics_btif(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::A2DP_CONNECTION_DISCONNECTED, 1);
if (peer_.SelfInitiatedConnection()) {
btif_queue_advance();
@@ -2203,7 +2202,7 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event, void* p_data
CHECK_RC_EVENT(event, reinterpret_cast<tBTA_AV*>(p_data));
default:
- log_counter_metrics_btif(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::A2DP_CONNECTION_UNKNOWN_EVENT, 1);
log::warn("Peer {} : Unhandled event={}", peer_.PeerAddress(), BtifAvEvent::EventName(event));
return false;
@@ -2933,7 +2932,7 @@ static void btif_report_audio_state(const RawAddress& peer_address, btav_audio_s
? AudioCodingModeEnum::AUDIO_CODING_MODE_HARDWARE
: AudioCodingModeEnum::AUDIO_CODING_MODE_SOFTWARE;
- log_a2dp_playback_event(peer_address, playback_state, audio_coding_mode);
+ bluetooth::shim::LogMetricA2dpPlaybackEvent(peer_address, playback_state, audio_coding_mode);
}
void btif_av_report_source_codec_state(
diff --git a/system/btif/src/btif_config.cc b/system/btif/src/btif_config.cc
index 2ee8fe494d..9a0e50dea1 100644
--- a/system/btif/src/btif_config.cc
+++ b/system/btif/src/btif_config.cc
@@ -32,9 +32,10 @@
#include <unordered_map>
#include "btif_keystore.h"
-#include "btif_metrics_logging.h"
#include "common/address_obfuscator.h"
#include "main/shim/config.h"
+#include "main/shim/metric_id_api.h"
+#include "main/shim/metrics_api.h"
#include "main/shim/shim.h"
#include "storage/config_keys.h"
#include "types/raw_address.h"
@@ -111,7 +112,7 @@ static void init_metric_id_allocator() {
// there is one metric id under this mac_address
int id = 0;
btif_config_get_int(addr_str, BTIF_STORAGE_KEY_METRICS_ID_KEY, &id);
- if (is_valid_id_from_metric_id_allocator(id)) {
+ if (bluetooth::shim::IsValidIdFromMetricIdAllocator(id)) {
paired_device_map[mac_address] = id;
is_valid_id_found = true;
}
@@ -128,15 +129,15 @@ static void init_metric_id_allocator() {
auto forget_device_callback = [](const RawAddress& address, const int /* id */) {
return btif_config_remove(address.ToString(), BTIF_STORAGE_KEY_METRICS_ID_KEY);
};
- if (!init_metric_id_allocator(paired_device_map, std::move(save_device_callback),
- std::move(forget_device_callback))) {
+ if (!bluetooth::shim::InitMetricIdAllocator(paired_device_map, std::move(save_device_callback),
+ std::move(forget_device_callback))) {
log::fatal("Failed to initialize MetricIdAllocator");
}
// Add device_without_id
for (auto& address : addresses_without_id) {
- allocate_metric_id_from_metric_id_allocator(address);
- save_metric_id_from_metric_id_allocator(address);
+ bluetooth::shim::AllocateIdFromMetricIdAllocator(address);
+ bluetooth::shim::SaveDeviceOnMetricIdAllocator(address);
}
}
@@ -160,7 +161,7 @@ static future_t* clean_up(void) {
"assert failed: bluetooth::shim::is_gd_stack_started_up()");
// GD storage module cleanup by itself
std::unique_lock<std::recursive_mutex> lock(config_lock);
- close_metric_id_allocator();
+ bluetooth::shim::CloseMetricIdAllocator();
return future_new_immediate(FUTURE_SUCCESS);
}
diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc
index 96ed5848b1..e10606b9dd 100644
--- a/system/btif/src/btif_dm.cc
+++ b/system/btif/src/btif_dm.cc
@@ -57,7 +57,6 @@
#include "btif_api.h"
#include "btif_bqr.h"
#include "btif_config.h"
-#include "btif_metrics_logging.h"
#include "btif_sdp.h"
#include "btif_storage.h"
#include "btif_util.h"
@@ -72,6 +71,8 @@
#include "main/shim/entry.h"
#include "main/shim/helpers.h"
#include "main/shim/le_advertising_manager.h"
+#include "main/shim/metric_id_api.h"
+#include "main/shim/metrics_api.h"
#include "main_thread.h"
#include "metrics/bluetooth_event.h"
#include "os/system_properties.h"
@@ -582,11 +583,11 @@ static void bond_state_changed(bt_status_t status, const RawAddress& bd_addr,
state, pairing_cb.state, pairing_cb.sdp_attempts);
if (state == BT_BOND_STATE_NONE) {
- forget_device_from_metric_id_allocator(bd_addr);
+ bluetooth::shim::ForgetDeviceFromMetricIdAllocator(bd_addr);
btif_config_remove_device(bd_addr.ToString());
} else if (state == BT_BOND_STATE_BONDED) {
- allocate_metric_id_from_metric_id_allocator(bd_addr);
- if (!save_metric_id_from_metric_id_allocator(bd_addr)) {
+ bluetooth::shim::AllocateIdFromMetricIdAllocator(bd_addr);
+ if (!bluetooth::shim::SaveDeviceOnMetricIdAllocator(bd_addr)) {
log::error("Fail to save metric id for device:{}", bd_addr);
}
}
@@ -1485,7 +1486,7 @@ static void btif_dm_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH*
auto triple = eir_uuids_cache.try_emplace(bdaddr, std::set<Uuid>{});
uuid_iter = std::get<0>(triple);
}
- log::info("EIR UUIDs for {}:", bdaddr);
+ log::info("EIR UUIDs for {}", bdaddr);
for (int i = 0; i < num_uuids; ++i) {
Uuid uuid = Uuid::From16Bit(p_uuid16[i]);
log::info("{}", uuid.ToString());
@@ -1608,7 +1609,7 @@ static void btif_on_service_discovery_results(RawAddress bd_addr,
if (results_for_bonding_device) {
// success for SDP
bluetooth::metrics::LogSDPComplete(bd_addr, tBTA_STATUS::BTA_SUCCESS);
- log::info("SDP finished for {}:", bd_addr);
+ log::info("SDP finished for {}", bd_addr);
pairing_cb.sdp_over_classic = btif_dm_pairing_cb_t::ServiceDiscoveryState::FINISHED;
}
@@ -1619,7 +1620,7 @@ static void btif_on_service_discovery_results(RawAddress bd_addr,
bt_property_t& le_prop = uuid_props[1];
if ((result == BTA_SUCCESS) && !uuids_param.empty()) {
- log::info("New UUIDs for {}:", bd_addr);
+ log::info("New UUIDs for {}", bd_addr);
for (const auto& uuid : uuids_param) {
if (btif_should_ignore_uuid(uuid)) {
continue;
@@ -1757,7 +1758,7 @@ static void btif_on_gatt_results(RawAddress bd_addr, std::vector<bluetooth::Uuid
bool lea_supported = is_le_audio_capable_during_service_discovery(bd_addr);
if (is_transport_le) {
- log::info("New GATT over LE UUIDs for {}:", bd_addr);
+ log::info("New GATT over LE UUIDs for {}", bd_addr);
BTM_LogHistory(kBtmLogTag, bd_addr, "Discovered GATT services using LE transport");
if (btif_is_gatt_service_discovery_post_pairing(bd_addr)) {
pairing_cb.gatt_over_le = btif_dm_pairing_cb_t::ServiceDiscoveryState::FINISHED;
@@ -1785,7 +1786,7 @@ static void btif_on_gatt_results(RawAddress bd_addr, std::vector<bluetooth::Uuid
}
}
} else {
- log::debug("New GATT over SDP UUIDs for {}:", bd_addr);
+ log::debug("New GATT over SDP UUIDs for {}", bd_addr);
BTM_LogHistory(kBtmLogTag, bd_addr, "Discovered GATT services using SDP transport");
}
diff --git a/system/btif/src/btif_hf.cc b/system/btif/src/btif_hf.cc
index 33fb900e07..178a1672e6 100644
--- a/system/btif/src/btif_hf.cc
+++ b/system/btif/src/btif_hf.cc
@@ -51,7 +51,6 @@
#include "bta/include/utl.h"
#include "bta_ag_swb_aptx.h"
#include "btif/include/btif_common.h"
-#include "btif/include/btif_metrics_logging.h"
#include "btif/include/btif_profile_queue.h"
#include "btif/include/btif_util.h"
#include "btm_api_types.h"
@@ -390,7 +389,7 @@ static void btif_hf_upstreams_evt(uint16_t event, char* p_param) {
p_data->open.status, btif_hf_cb[idx].connected_bda, p_data->open.bd_addr);
bt_hf_callbacks->ConnectionStateCallback(BTHF_CONNECTION_STATE_DISCONNECTED,
&(p_data->open.bd_addr));
- log_counter_metrics_btif(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HFP_COLLISON_AT_AG_OPEN, 1);
}
break;
@@ -412,7 +411,7 @@ static void btif_hf_upstreams_evt(uint16_t event, char* p_param) {
btif_hf_cb[idx].connected_bda, p_data->open.bd_addr);
bt_hf_callbacks->ConnectionStateCallback(BTHF_CONNECTION_STATE_DISCONNECTED,
&(btif_hf_cb[idx].connected_bda));
- log_counter_metrics_btif(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HFP_COLLISON_AT_CONNECTING, 1);
reset_control_block(&btif_hf_cb[idx]);
btif_queue_advance();
@@ -472,7 +471,7 @@ static void btif_hf_upstreams_evt(uint16_t event, char* p_param) {
bt_hf_callbacks->ConnectionStateCallback(btif_hf_cb[idx].state, &connected_bda);
}
- log_counter_metrics_btif(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HFP_SELF_INITIATED_AG_FAILED, 1);
btif_queue_advance();
if (btm_sec_is_a_bonded_dev(connected_bda)) {
@@ -496,8 +495,8 @@ static void btif_hf_upstreams_evt(uint16_t event, char* p_param) {
bt_hf_callbacks->ConnectionStateCallback(btif_hf_cb[idx].state, &connected_bda);
if (failed_to_setup_slc) {
log::error("failed to setup SLC for {}", connected_bda);
- log_counter_metrics_btif(android::bluetooth::CodePathCounterKeyEnum::HFP_SLC_SETUP_FAILED,
- 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::HFP_SLC_SETUP_FAILED, 1);
btif_queue_advance();
LogMetricHfpSlcFail(ToGdAddress(p_data->open.bd_addr));
DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(btif_hf_cb[idx].connected_bda,
@@ -881,7 +880,7 @@ public:
bt_status_t DisconnectAudio(RawAddress* bd_addr) override;
bt_status_t isNoiseReductionSupported(RawAddress* bd_addr) override;
bt_status_t isVoiceRecognitionSupported(RawAddress* bd_addr) override;
- bt_status_t StartVoiceRecognition(RawAddress* bd_addr) override;
+ bt_status_t StartVoiceRecognition(RawAddress* bd_addr, bool sendResult) override;
bt_status_t StopVoiceRecognition(RawAddress* bd_addr) override;
bt_status_t VolumeControl(bthf_volume_type_t type, int volume, RawAddress* bd_addr) override;
bt_status_t DeviceStatusNotification(bthf_network_state_t ntk_state, bthf_service_type_t svc_type,
@@ -1024,7 +1023,7 @@ bt_status_t HeadsetInterface::isVoiceRecognitionSupported(RawAddress* bd_addr) {
return BT_STATUS_SUCCESS;
}
-bt_status_t HeadsetInterface::StartVoiceRecognition(RawAddress* bd_addr) {
+bt_status_t HeadsetInterface::StartVoiceRecognition(RawAddress* bd_addr, bool sendResult) {
CHECK_BTHF_INIT();
int idx = btif_hf_idx_by_bdaddr(bd_addr);
if ((idx < 0) || (idx >= BTA_AG_MAX_NUM_CLIENTS)) {
@@ -1040,9 +1039,11 @@ bt_status_t HeadsetInterface::StartVoiceRecognition(RawAddress* bd_addr) {
return BT_STATUS_UNSUPPORTED;
}
btif_hf_cb[idx].is_during_voice_recognition = true;
- tBTA_AG_RES_DATA ag_res = {};
- ag_res.state = true;
- BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, ag_res);
+ if (sendResult) {
+ tBTA_AG_RES_DATA ag_res = {};
+ ag_res.state = true;
+ BTA_AgResult(btif_hf_cb[idx].handle, BTA_AG_BVRA_RES, ag_res);
+ }
return BT_STATUS_SUCCESS;
}
diff --git a/system/btif/src/btif_hh.cc b/system/btif/src/btif_hh.cc
index 7288abe98c..28ed77113d 100644
--- a/system/btif/src/btif_hh.cc
+++ b/system/btif/src/btif_hh.cc
@@ -48,7 +48,6 @@
#include "btif/include/btif_common.h"
#include "btif/include/btif_dm.h"
#include "btif/include/btif_hd.h"
-#include "btif/include/btif_metrics_logging.h"
#include "btif/include/btif_profile_storage.h"
#include "btif/include/btif_storage.h"
#include "btif/include/btif_util.h"
@@ -56,6 +55,7 @@
#include "include/hardware/bt_hh.h"
#include "internal_include/bt_target.h"
#include "main/shim/dumpsys.h"
+#include "main/shim/metrics_api.h"
#include "osi/include/alarm.h"
#include "osi/include/allocator.h"
#include "stack/include/bt_hdr.h"
@@ -468,7 +468,7 @@ static void btif_hh_incoming_connection_timeout(void* data) {
handle);
}
log::warn("Reject unexpected incoming HID Connection, device: {}", conn.link_spec);
- log_counter_metrics_btif(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_COUNT_INCOMING_CONNECTION_REJECTED, 1);
btif_hh_device_t* p_dev = btif_hh_find_dev_by_link_spec(conn.link_spec);
@@ -529,7 +529,7 @@ static bool hh_add_device(const tAclLinkSpec& link_spec, tBTA_HH_ATTR_MASK attr_
}
log::error("Out of space to add device");
- log_counter_metrics_btif(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_COUNT_MAX_ADDED_DEVICE_LIMIT_REACHED, 1);
return false;
}
@@ -633,7 +633,7 @@ static void hh_open_handler(tBTA_HH_CONN& conn) {
log::warn("Reject Incoming HID Connection, device: {}, state: {}", conn.link_spec,
bthh_connection_state_text(dev_status));
- log_counter_metrics_btif(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_COUNT_INCOMING_CONNECTION_REJECTED, 1);
if (p_dev != nullptr) {
@@ -749,9 +749,7 @@ static void hh_get_rpt_handler(tBTA_HH_HSDATA& hs_data) {
HAL_CBACK(bt_hh_callbacks, handshake_cb, (RawAddress*)&(p_dev->link_spec.addrt.bda),
p_dev->link_spec.addrt.type, p_dev->link_spec.transport,
(bthh_status_t)hs_data.status);
- if (com::android::bluetooth::flags::forward_get_set_report_failure_to_uhid()) {
- bta_hh_co_get_rpt_rsp(p_dev->dev_handle, (tBTA_HH_STATUS)hs_data.status, NULL, 0);
- }
+ bta_hh_co_get_rpt_rsp(p_dev->dev_handle, (tBTA_HH_STATUS)hs_data.status, NULL, 0);
}
}
@@ -910,9 +908,10 @@ static void hh_vc_unplug_handler(tBTA_HH_CBDATA& dev_status) {
BTHH_STATE_UPDATE(p_dev->link_spec, p_dev->dev_status);
if (!p_dev->local_vup) {
- log_counter_metrics_btif(android::bluetooth::CodePathCounterKeyEnum::
- HIDH_COUNT_VIRTUAL_UNPLUG_REQUESTED_BY_REMOTE_DEVICE,
- 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::
+ HIDH_COUNT_VIRTUAL_UNPLUG_REQUESTED_BY_REMOTE_DEVICE,
+ 1);
}
// Remove the HID device
@@ -1193,9 +1192,10 @@ bt_status_t btif_hh_connect(const tAclLinkSpec& link_spec) {
if (!p_dev && btif_hh_cb.device_num >= BTIF_HH_MAX_HID) {
// No space for more HID device now.
log::warn("Error, exceeded the maximum supported HID device number {}", BTIF_HH_MAX_HID);
- log_counter_metrics_btif(android::bluetooth::CodePathCounterKeyEnum::
- HIDH_COUNT_CONNECT_REQ_WHEN_MAX_DEVICE_LIMIT_REACHED,
- 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::
+ HIDH_COUNT_CONNECT_REQ_WHEN_MAX_DEVICE_LIMIT_REACHED,
+ 1);
return BT_STATUS_NOMEM;
}
@@ -2030,7 +2030,7 @@ static bt_status_t get_report(RawAddress* bd_addr, tBLE_ADDR_TYPE addr_type,
return BT_STATUS_DEVICE_NOT_FOUND;
} else if (((int)reportType) <= BTA_HH_RPTT_RESRV || ((int)reportType) > BTA_HH_RPTT_FEATURE) {
log::error("report type={} not supported", reportType);
- log_counter_metrics_btif(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_COUNT_WRONG_REPORT_TYPE, 1);
return BT_STATUS_UNSUPPORTED;
} else {
@@ -2102,7 +2102,7 @@ static bt_status_t set_report(RawAddress* bd_addr, tBLE_ADDR_TYPE addr_type,
return BT_STATUS_DEVICE_NOT_FOUND;
} else if (((int)reportType) <= BTA_HH_RPTT_RESRV || ((int)reportType) > BTA_HH_RPTT_FEATURE) {
log::error("report type={} not supported", reportType);
- log_counter_metrics_btif(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_COUNT_WRONG_REPORT_TYPE, 1);
return BT_STATUS_UNSUPPORTED;
} else {
diff --git a/system/btif/src/btif_metrics_logging.cc b/system/btif/src/btif_metrics_logging.cc
deleted file mode 100644
index 40f2fed315..0000000000
--- a/system/btif/src/btif_metrics_logging.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2021 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.
- */
-
-#include "btif/include/btif_metrics_logging.h"
-
-#include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
-#include <frameworks/proto_logging/stats/enums/bluetooth/hci/enums.pb.h>
-
-#include "main/shim/metrics_api.h"
-#include "types/raw_address.h"
-
-void log_a2dp_audio_underrun_event(const RawAddress& address, uint64_t encoding_interval_millis,
- int num_missing_pcm_bytes) {
- bluetooth::shim::LogMetricA2dpAudioUnderrunEvent(address, encoding_interval_millis,
- num_missing_pcm_bytes);
-}
-
-void log_a2dp_audio_overrun_event(const RawAddress& address, uint64_t encoding_interval_millis,
- int num_dropped_buffers, int num_dropped_encoded_frames,
- int num_dropped_encoded_bytes) {
- bluetooth::shim::LogMetricA2dpAudioOverrunEvent(address, encoding_interval_millis,
- num_dropped_buffers, num_dropped_encoded_frames,
- num_dropped_encoded_bytes);
-}
-
-void log_a2dp_playback_event(const RawAddress& address, int playback_state, int audio_coding_mode) {
- bluetooth::shim::LogMetricA2dpPlaybackEvent(address, playback_state, audio_coding_mode);
-}
-
-void log_a2dp_session_metrics_event(const RawAddress& address, int64_t audio_duration_ms,
- int media_timer_min_ms, int media_timer_max_ms,
- int media_timer_avg_ms, int total_scheduling_count,
- int buffer_overruns_max_count, int buffer_overruns_total,
- float buffer_underruns_average, int buffer_underruns_count,
- int64_t codec_index, bool is_a2dp_offload) {
- bluetooth::shim::LogMetricA2dpSessionMetricsEvent(
- address, audio_duration_ms, media_timer_min_ms, media_timer_max_ms, media_timer_avg_ms,
- total_scheduling_count, buffer_overruns_max_count, buffer_overruns_total,
- buffer_underruns_average, buffer_underruns_count, codec_index, is_a2dp_offload);
-}
-
-void log_read_rssi_result(const RawAddress& address, uint16_t handle, uint32_t cmd_status,
- int8_t rssi) {
- bluetooth::shim::LogMetricReadRssiResult(address, handle, cmd_status, rssi);
-}
-
-void log_read_failed_contact_counter_result(const RawAddress& address, uint16_t handle,
- uint32_t cmd_status, int32_t failed_contact_counter) {
- bluetooth::shim::LogMetricReadFailedContactCounterResult(address, handle, cmd_status,
- failed_contact_counter);
-}
-
-void log_read_tx_power_level_result(const RawAddress& address, uint16_t handle, uint32_t cmd_status,
- int32_t transmit_power_level) {
- bluetooth::shim::LogMetricReadTxPowerLevelResult(address, handle, cmd_status,
- transmit_power_level);
-}
-
-void log_socket_connection_state(const RawAddress& address, int port, int type,
- android::bluetooth::SocketConnectionstateEnum connection_state,
- int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port,
- android::bluetooth::SocketRoleEnum socket_role,
- uint64_t connection_duration_ms,
- android::bluetooth::SocketErrorEnum error_code,
- bool is_hardware_offload) {
- bluetooth::shim::LogMetricSocketConnectionState(
- address, port, type, connection_state, tx_bytes, rx_bytes, uid, server_port, socket_role,
- connection_duration_ms, error_code, is_hardware_offload);
-}
-
-void log_counter_metrics_btif(android::bluetooth::CodePathCounterKeyEnum key, int64_t value) {
- bluetooth::shim::CountCounterMetrics(key, value);
-}
-
-bool init_metric_id_allocator(const std::unordered_map<RawAddress, int>& paired_device_map,
- bluetooth::shim::CallbackLegacy save_device_callback,
- bluetooth::shim::CallbackLegacy forget_device_callback) {
- return bluetooth::shim::InitMetricIdAllocator(paired_device_map, std::move(save_device_callback),
- std::move(forget_device_callback));
-}
-
-bool close_metric_id_allocator() { return bluetooth::shim::CloseMetricIdAllocator(); }
-
-int allocate_metric_id_from_metric_id_allocator(const RawAddress& address) {
- return bluetooth::shim::AllocateIdFromMetricIdAllocator(address);
-}
-
-int save_metric_id_from_metric_id_allocator(const RawAddress& address) {
- return bluetooth::shim::SaveDeviceOnMetricIdAllocator(address);
-}
-
-void forget_device_from_metric_id_allocator(const RawAddress& address) {
- bluetooth::shim::ForgetDeviceFromMetricIdAllocator(address);
-}
-
-bool is_valid_id_from_metric_id_allocator(const int id) {
- return bluetooth::shim::IsValidIdFromMetricIdAllocator(id);
-}
diff --git a/system/btif/src/btif_sock_logging.cc b/system/btif/src/btif_sock_logging.cc
index 111e52002b..8847daa7f1 100644
--- a/system/btif/src/btif_sock_logging.cc
+++ b/system/btif/src/btif_sock_logging.cc
@@ -23,9 +23,9 @@
#include <atomic>
-#include "btif/include/btif_metrics_logging.h"
#include "btif/include/btif_sock.h"
#include "common/time_util.h"
+#include "main/shim/metrics_api.h"
#include "types/raw_address.h"
#define SOCK_LOGGER_SIZE_MAX 16
@@ -79,7 +79,7 @@ void btif_sock_connection_logger(const RawAddress& address, int port, int type,
}
clock_gettime(CLOCK_REALTIME, &connection_logger[index].timestamp);
- log_socket_connection_state(
+ bluetooth::shim::LogMetricSocketConnectionState(
address, port, type, toConnectionStateEnum(state), tx_bytes, rx_bytes, uid, server_port,
toSocketRoleEnum(role), getConnectionDuration(connection_start_time_ms),
toSocketErrorEnum(error_code), data_path == BTSOCK_DATA_PATH_HARDWARE_OFFLOAD);
diff --git a/system/btif/src/btif_sock_rfc.cc b/system/btif/src/btif_sock_rfc.cc
index 4c75b0f355..1ea4bf9981 100644
--- a/system/btif/src/btif_sock_rfc.cc
+++ b/system/btif/src/btif_sock_rfc.cc
@@ -33,7 +33,6 @@
#include "bta/include/bta_jv_co.h"
#include "bta/include/bta_rfcomm_metrics.h"
#include "bta/include/bta_rfcomm_scn.h"
-#include "btif/include/btif_metrics_logging.h"
#include "btif/include/btif_sock.h"
#include "btif/include/btif_sock_l2cap.h"
#include "btif/include/btif_sock_logging.h"
@@ -45,6 +44,7 @@
#include "include/hardware/bt_sock.h"
#include "lpp/lpp_offload_interface.h"
#include "main/shim/entry.h"
+#include "main/shim/metrics_api.h"
#include "osi/include/allocator.h"
#include "osi/include/compat.h"
#include "osi/include/list.h"
@@ -909,12 +909,12 @@ static void on_rfc_close(tBTA_JV_RFCOMM_CLOSE* /* p_close */, uint32_t id) {
log::warn("RFCOMM slot with id {} not found.", id);
return;
}
- log_socket_connection_state(slot->addr, slot->id, BTSOCK_RFCOMM,
- android::bluetooth::SOCKET_CONNECTION_STATE_DISCONNECTING, 0, 0,
- slot->app_uid, slot->scn,
- slot->f.server ? android::bluetooth::SOCKET_ROLE_LISTEN
- : android::bluetooth::SOCKET_ROLE_CONNECTION,
- 0, android::bluetooth::SOCKET_ERROR_NONE, slot->data_path);
+ bluetooth::shim::LogMetricSocketConnectionState(
+ slot->addr, slot->id, BTSOCK_RFCOMM,
+ android::bluetooth::SOCKET_CONNECTION_STATE_DISCONNECTING, 0, 0, slot->app_uid, slot->scn,
+ slot->f.server ? android::bluetooth::SOCKET_ROLE_LISTEN
+ : android::bluetooth::SOCKET_ROLE_CONNECTION,
+ 0, android::bluetooth::SOCKET_ERROR_NONE, slot->data_path);
cleanup_rfc_slot(slot, BTSOCK_ERROR_NONE);
}
diff --git a/system/btif/test/btif_core_test.cc b/system/btif/test/btif_core_test.cc
index 7342a17b99..3073bd194c 100644
--- a/system/btif/test/btif_core_test.cc
+++ b/system/btif/test/btif_core_test.cc
@@ -207,7 +207,8 @@ class BtifCoreTest : public ::testing::Test {
protected:
void SetUp() override {
callback_map_.clear();
- bluetooth::hci::testing::mock_controller_ = &controller_;
+ bluetooth::hci::testing::mock_controller_ =
+ std::make_unique<bluetooth::hci::testing::MockControllerInterface>();
bluetooth::testing::set_hal_cbacks(&callbacks);
auto promise = std::promise<void>();
auto future = promise.get_future();
@@ -223,17 +224,17 @@ protected:
callback_map_["callback_thread_event"] = [&promise]() { promise.set_value(); };
CleanCoreInterface();
ASSERT_EQ(std::future_status::ready, future.wait_for(timeout_time));
- bluetooth::hci::testing::mock_controller_ = nullptr;
+ bluetooth::hci::testing::mock_controller_.reset();
callback_map_.erase("callback_thread_event");
}
- bluetooth::hci::testing::MockControllerInterface controller_;
};
class BtifCoreWithControllerTest : public BtifCoreTest {
protected:
void SetUp() override {
BtifCoreTest::SetUp();
- ON_CALL(controller_, SupportsSniffSubrating).WillByDefault(Return(true));
+ ON_CALL(*bluetooth::hci::testing::mock_controller_, SupportsSniffSubrating)
+ .WillByDefault(Return(true));
}
void TearDown() override { BtifCoreTest::TearDown(); }
@@ -761,12 +762,13 @@ class BtifCoreWithVendorSupportTest : public BtifCoreWithControllerTest {
protected:
void SetUp() override {
BtifCoreWithControllerTest::SetUp();
- bluetooth::hci::testing::mock_hci_layer_ = &hci_;
+ bluetooth::hci::testing::mock_hci_layer_ =
+ std::make_unique<bluetooth::hci::testing::MockHciLayer>();
test::mock::osi_properties::osi_property_get.body = get_properties;
std::promise<void> configuration_promise;
auto configuration_done = configuration_promise.get_future();
- EXPECT_CALL(hci_,
+ EXPECT_CALL(*bluetooth::hci::testing::mock_hci_layer_,
EnqueueCommand(_, Matcher<ContextualOnceCallback<void(CommandCompleteView)>>(_)))
.WillOnce(
// Replace with real PDL for 0xfc17
@@ -784,7 +786,7 @@ protected:
configuration_promise.set_value();
})
.RetiresOnSaturation();
- EXPECT_CALL(hci_,
+ EXPECT_CALL(*bluetooth::hci::testing::mock_hci_layer_,
EnqueueCommand(_, Matcher<ContextualOnceCallback<void(CommandCompleteView)>>(_)))
.WillOnce([](std::unique_ptr<CommandBuilder> cmd,
ContextualOnceCallback<void(CommandCompleteView)> callback) {
@@ -798,7 +800,8 @@ protected:
callback(response);
})
.RetiresOnSaturation();
- EXPECT_CALL(hci_, RegisterVendorSpecificEventHandler(VseSubeventCode::BQR_EVENT, _))
+ EXPECT_CALL(*bluetooth::hci::testing::mock_hci_layer_,
+ RegisterVendorSpecificEventHandler(VseSubeventCode::BQR_EVENT, _))
.WillOnce(SaveArg<1>(&this->vse_callback_));
do_in_main_thread(BindOnce([]() { bluetooth::bqr::EnableBtQualityReport(get_main()); }));
ASSERT_EQ(std::future_status::ready, configuration_done.wait_for(std::chrono::seconds(1)));
@@ -808,18 +811,18 @@ protected:
std::promise<void> disable_promise;
auto disable_future = disable_promise.get_future();
auto set_promise = [&disable_promise]() { disable_promise.set_value(); };
- EXPECT_CALL(hci_, UnregisterVendorSpecificEventHandler(VseSubeventCode::BQR_EVENT));
- EXPECT_CALL(hci_,
+ EXPECT_CALL(*bluetooth::hci::testing::mock_hci_layer_,
+ UnregisterVendorSpecificEventHandler(VseSubeventCode::BQR_EVENT));
+ EXPECT_CALL(*bluetooth::hci::testing::mock_hci_layer_,
EnqueueCommand(_, Matcher<ContextualOnceCallback<void(CommandCompleteView)>>(_)))
.WillOnce(Invoke(set_promise))
.RetiresOnSaturation();
do_in_main_thread(BindOnce([]() { bluetooth::bqr::DisableBtQualityReport(); }));
ASSERT_EQ(std::future_status::ready, disable_future.wait_for(std::chrono::seconds(1)));
- bluetooth::hci::testing::mock_hci_layer_ = nullptr;
+ bluetooth::hci::testing::mock_hci_layer_.reset();
BtifCoreWithControllerTest::TearDown();
}
- bluetooth::hci::testing::MockHciLayer hci_;
ContextualCallback<void(VendorSpecificEventView)> vse_callback_;
};
diff --git a/system/common/Android.bp b/system/common/Android.bp
index c192613dbc..a22a733e75 100644
--- a/system/common/Android.bp
+++ b/system/common/Android.bp
@@ -32,17 +32,6 @@ cc_library_static {
canonical_path_from_root: false,
export_proto_headers: true,
},
- target: {
- android: {
- srcs: [
- "metrics.cc",
- ],
- static_libs: ["libstatslog_bt"],
- },
- host: {
- srcs: ["metrics_linux.cc"],
- },
- },
shared_libs: [
"libcrypto",
"libcutils",
diff --git a/system/common/BUILD.gn b/system/common/BUILD.gn
index a1884973dd..5b0852bd36 100644
--- a/system/common/BUILD.gn
+++ b/system/common/BUILD.gn
@@ -19,8 +19,6 @@ static_library("common") {
"address_obfuscator.cc",
"le_conn_params.cc",
"message_loop_thread.cc",
- "metric_id_allocator.cc",
- "metrics_linux.cc",
"os_utils.cc",
"repeating_timer.cc",
"stop_watch_legacy.cc",
@@ -30,7 +28,6 @@ static_library("common") {
include_dirs = [
"//bt/system/",
"//bt/system/stack/include",
- "//bt/system/linux_include",
]
deps = [
diff --git a/system/common/metrics.cc b/system/common/metrics.cc
deleted file mode 100644
index a3b3eea450..0000000000
--- a/system/common/metrics.cc
+++ /dev/null
@@ -1,433 +0,0 @@
-/******************************************************************************
- *
- * Copyright 2016 Google, Inc.
- *
- * 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.
- *
- ******************************************************************************/
-
-#include "common/metrics.h"
-
-#include <base/base64.h>
-#include <bluetooth/log.h>
-#include <frameworks/proto_logging/stats/enums/bluetooth/le/enums.pb.h>
-#include <include/hardware/bt_av.h>
-#include <statslog_bt.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <cerrno>
-#include <cstdint>
-#include <cstring>
-#include <memory>
-#include <mutex> // NOLINT
-#include <utility>
-
-#include "common/address_obfuscator.h"
-#include "common/leaky_bonded_queue.h"
-#include "common/time_util.h"
-#include "hci/address.h"
-#include "main/shim/metric_id_api.h"
-#include "osi/include/osi.h"
-#include "types/raw_address.h"
-
-namespace std {
-template <>
-struct formatter<android::bluetooth::DirectionEnum>
- : enum_formatter<android::bluetooth::DirectionEnum> {};
-template <>
-struct formatter<android::bluetooth::SocketConnectionstateEnum>
- : enum_formatter<android::bluetooth::SocketConnectionstateEnum> {};
-template <>
-struct formatter<android::bluetooth::SocketRoleEnum>
- : enum_formatter<android::bluetooth::SocketRoleEnum> {};
-template <>
-struct formatter<android::bluetooth::AddressTypeEnum>
- : enum_formatter<android::bluetooth::AddressTypeEnum> {};
-template <>
-struct formatter<android::bluetooth::DeviceInfoSrcEnum>
- : enum_formatter<android::bluetooth::DeviceInfoSrcEnum> {};
-template <>
-struct formatter<android::bluetooth::SocketErrorEnum>
- : enum_formatter<android::bluetooth::SocketErrorEnum> {};
-} // namespace std
-
-namespace bluetooth {
-namespace common {
-
-using bluetooth::hci::Address;
-
-void LogLinkLayerConnectionEvent(const RawAddress* address, uint32_t connection_handle,
- android::bluetooth::DirectionEnum direction, uint16_t link_type,
- uint32_t hci_cmd, uint16_t hci_event, uint16_t hci_ble_event,
- uint16_t cmd_status, uint16_t reason_code) {
- std::string obfuscated_id;
- int metric_id = 0;
- if (address != nullptr) {
- obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(*address);
- metric_id = bluetooth::shim::AllocateIdFromMetricIdAllocator(*address);
- }
- // nullptr and size 0 represent missing value for obfuscated_id
- BytesField bytes_field(address != nullptr ? obfuscated_id.c_str() : nullptr,
- address != nullptr ? obfuscated_id.size() : 0);
- int ret = stats_write(BLUETOOTH_LINK_LAYER_CONNECTION_EVENT, bytes_field, connection_handle,
- direction, link_type, hci_cmd, hci_event, hci_ble_event, cmd_status,
- reason_code, metric_id);
- if (ret < 0) {
- log::warn(
- "failed to log status 0x{:x}, reason 0x{:x} from cmd 0x{:x}, event "
- "0x{:x}, ble_event 0x{:x} for {}, handle {}, type 0x{:x}, error {}",
- cmd_status, reason_code, hci_cmd, hci_event, hci_ble_event, *address, connection_handle,
- link_type, ret);
- }
-}
-
-void LogHciTimeoutEvent(uint32_t hci_cmd) {
- int ret = stats_write(BLUETOOTH_HCI_TIMEOUT_REPORTED, static_cast<int64_t>(hci_cmd));
- if (ret < 0) {
- log::warn("failed for opcode 0x{:x}, error {}", hci_cmd, ret);
- }
-}
-
-void LogRemoteVersionInfo(uint16_t handle, uint8_t status, uint8_t version,
- uint16_t manufacturer_name, uint16_t subversion) {
- int ret = stats_write(BLUETOOTH_REMOTE_VERSION_INFO_REPORTED, handle, status, version,
- manufacturer_name, subversion);
- if (ret < 0) {
- log::warn(
- "failed for handle {}, status 0x{:x}, version 0x{:x}, "
- "manufacturer_name 0x{:x}, subversion 0x{:x}, error {}",
- handle, status, version, manufacturer_name, subversion, ret);
- }
-}
-
-void LogA2dpAudioUnderrunEvent(const RawAddress& address, uint64_t encoding_interval_millis,
- int num_missing_pcm_bytes) {
- std::string obfuscated_id;
- int metric_id = 0;
- if (!address.IsEmpty()) {
- obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
- metric_id = bluetooth::shim::AllocateIdFromMetricIdAllocator(address);
- }
- // nullptr and size 0 represent missing value for obfuscated_id
- BytesField bytes_field(address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
- address.IsEmpty() ? 0 : obfuscated_id.size());
- int64_t encoding_interval_nanos = encoding_interval_millis * 1000000;
- int ret = stats_write(BLUETOOTH_A2DP_AUDIO_UNDERRUN_REPORTED, bytes_field,
- encoding_interval_nanos, num_missing_pcm_bytes, metric_id);
- if (ret < 0) {
- log::warn(
- "failed for {}, encoding_interval_nanos {}, num_missing_pcm_bytes {}, "
- "error {}",
- address, encoding_interval_nanos, num_missing_pcm_bytes, ret);
- }
-}
-
-void LogA2dpAudioOverrunEvent(const RawAddress& address, uint64_t encoding_interval_millis,
- int num_dropped_buffers, int num_dropped_encoded_frames,
- int num_dropped_encoded_bytes) {
- std::string obfuscated_id;
- int metric_id = 0;
- if (!address.IsEmpty()) {
- obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
- metric_id = bluetooth::shim::AllocateIdFromMetricIdAllocator(address);
- }
- // nullptr and size 0 represent missing value for obfuscated_id
- BytesField bytes_field(address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
- address.IsEmpty() ? 0 : obfuscated_id.size());
- int64_t encoding_interval_nanos = encoding_interval_millis * 1000000;
- int ret = stats_write(BLUETOOTH_A2DP_AUDIO_OVERRUN_REPORTED, bytes_field, encoding_interval_nanos,
- num_dropped_buffers, num_dropped_encoded_frames, num_dropped_encoded_bytes,
- metric_id);
- if (ret < 0) {
- log::warn(
- "failed to log for {}, encoding_interval_nanos {}, num_dropped_buffers "
- "{}, num_dropped_encoded_frames {}, num_dropped_encoded_bytes {}, "
- "error {}",
- address, encoding_interval_nanos, num_dropped_buffers, num_dropped_encoded_frames,
- num_dropped_encoded_bytes, ret);
- }
-}
-
-void LogA2dpPlaybackEvent(const RawAddress& address, int playback_state, int audio_coding_mode) {
- std::string obfuscated_id;
- int metric_id = 0;
- if (!address.IsEmpty()) {
- obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
- metric_id = bluetooth::shim::AllocateIdFromMetricIdAllocator(address);
- }
- // nullptr and size 0 represent missing value for obfuscated_id
- BytesField bytes_field(address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
- address.IsEmpty() ? 0 : obfuscated_id.size());
- int ret = stats_write(BLUETOOTH_A2DP_PLAYBACK_STATE_CHANGED, bytes_field, playback_state,
- audio_coding_mode, metric_id);
- if (ret < 0) {
- log::warn(
- "failed to log for {}, playback_state {}, audio_coding_mode {}, error "
- "{}",
- address, playback_state, audio_coding_mode, ret);
- }
-}
-
-void LogReadRssiResult(const RawAddress& address, uint16_t handle, uint32_t cmd_status,
- int8_t rssi) {
- std::string obfuscated_id;
- int metric_id = 0;
- if (!address.IsEmpty()) {
- obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
- metric_id = bluetooth::shim::AllocateIdFromMetricIdAllocator(address);
- }
- // nullptr and size 0 represent missing value for obfuscated_id
- BytesField bytes_field(address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
- address.IsEmpty() ? 0 : obfuscated_id.size());
- int ret = stats_write(BLUETOOTH_DEVICE_RSSI_REPORTED, bytes_field, handle, cmd_status, rssi,
- metric_id);
- if (ret < 0) {
- log::warn("failed for {}, handle {}, status 0x{:x}, rssi {} dBm, error {}", address, handle,
- cmd_status, rssi, ret);
- }
-}
-
-void LogReadFailedContactCounterResult(const RawAddress& address, uint16_t handle,
- uint32_t cmd_status, int32_t failed_contact_counter) {
- std::string obfuscated_id;
- int metric_id = 0;
- if (!address.IsEmpty()) {
- obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
- metric_id = bluetooth::shim::AllocateIdFromMetricIdAllocator(address);
- }
- // nullptr and size 0 represent missing value for obfuscated_id
- BytesField bytes_field(address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
- address.IsEmpty() ? 0 : obfuscated_id.size());
- int ret = stats_write(BLUETOOTH_DEVICE_FAILED_CONTACT_COUNTER_REPORTED, bytes_field, handle,
- cmd_status, failed_contact_counter, metric_id);
- if (ret < 0) {
- log::warn(
- "failed for {}, handle {}, status 0x{:x}, failed_contact_counter {} "
- "packets, error {}",
- address, handle, cmd_status, failed_contact_counter, ret);
- }
-}
-
-void LogReadTxPowerLevelResult(const RawAddress& address, uint16_t handle, uint32_t cmd_status,
- int32_t transmit_power_level) {
- std::string obfuscated_id;
- int metric_id = 0;
- if (!address.IsEmpty()) {
- obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
- metric_id = bluetooth::shim::AllocateIdFromMetricIdAllocator(address);
- }
- // nullptr and size 0 represent missing value for obfuscated_id
- BytesField bytes_field(address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
- address.IsEmpty() ? 0 : obfuscated_id.size());
- int ret = stats_write(BLUETOOTH_DEVICE_TX_POWER_LEVEL_REPORTED, bytes_field, handle, cmd_status,
- transmit_power_level, metric_id);
- if (ret < 0) {
- log::warn(
- "failed for {}, handle {}, status 0x{:x}, transmit_power_level {} "
- "packets, error {}",
- address, handle, cmd_status, transmit_power_level, ret);
- }
-}
-
-void LogSmpPairingEvent(const RawAddress& address, uint8_t smp_cmd,
- android::bluetooth::DirectionEnum direction, uint8_t smp_fail_reason) {
- std::string obfuscated_id;
- int metric_id = 0;
- if (!address.IsEmpty()) {
- obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
- metric_id = bluetooth::shim::AllocateIdFromMetricIdAllocator(address);
- }
- // nullptr and size 0 represent missing value for obfuscated_id
- BytesField obfuscated_id_field(address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
- address.IsEmpty() ? 0 : obfuscated_id.size());
- int ret = stats_write(BLUETOOTH_SMP_PAIRING_EVENT_REPORTED, obfuscated_id_field, smp_cmd,
- direction, smp_fail_reason, metric_id);
- if (ret < 0) {
- log::warn(
- "failed for {}, smp_cmd 0x{:x}, direction {}, smp_fail_reason 0x{:x}, "
- "error {}",
- address, smp_cmd, direction, smp_fail_reason, ret);
- }
-}
-
-void LogClassicPairingEvent(const RawAddress& address, uint16_t handle, uint32_t hci_cmd,
- uint16_t hci_event, uint16_t cmd_status, uint16_t reason_code,
- int64_t event_value) {
- std::string obfuscated_id;
- int metric_id = 0;
- if (!address.IsEmpty()) {
- obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
- metric_id = bluetooth::shim::AllocateIdFromMetricIdAllocator(address);
- }
- // nullptr and size 0 represent missing value for obfuscated_id
- BytesField obfuscated_id_field(address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
- address.IsEmpty() ? 0 : obfuscated_id.size());
- int ret = stats_write(BLUETOOTH_CLASSIC_PAIRING_EVENT_REPORTED, obfuscated_id_field, handle,
- hci_cmd, hci_event, cmd_status, reason_code, event_value, metric_id);
- if (ret < 0) {
- log::warn(
- "failed for {}, handle {}, hci_cmd 0x{:x}, hci_event 0x{:x}, "
- "cmd_status 0x{:x}, reason 0x{:x}, event_value {}, error {}",
- address, handle, hci_cmd, hci_event, cmd_status, reason_code, event_value, ret);
- }
-}
-
-void LogSdpAttribute(const RawAddress& address, uint16_t protocol_uuid, uint16_t attribute_id,
- size_t attribute_size, const char* attribute_value) {
- std::string obfuscated_id;
- int metric_id = 0;
- if (!address.IsEmpty()) {
- obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
- metric_id = bluetooth::shim::AllocateIdFromMetricIdAllocator(address);
- }
- // nullptr and size 0 represent missing value for obfuscated_id
- BytesField obfuscated_id_field(address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
- address.IsEmpty() ? 0 : obfuscated_id.size());
- BytesField attribute_field(attribute_value, attribute_size);
- int ret = stats_write(BLUETOOTH_SDP_ATTRIBUTE_REPORTED, obfuscated_id_field, protocol_uuid,
- attribute_id, attribute_field, metric_id);
- if (ret < 0) {
- log::warn("failed for {}, protocol_uuid 0x{:x}, attribute_id 0x{:x}, error {}", address,
- protocol_uuid, attribute_id, ret);
- }
-}
-
-void LogSocketConnectionState(const RawAddress& address, int port, int type,
- android::bluetooth::SocketConnectionstateEnum connection_state,
- int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port,
- android::bluetooth::SocketRoleEnum socket_role,
- uint64_t connection_duration_ms,
- android::bluetooth::SocketErrorEnum error_code,
- bool is_hardware_offload) {
- std::string obfuscated_id;
- int metric_id = 0;
- if (!address.IsEmpty()) {
- obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
- metric_id = bluetooth::shim::AllocateIdFromMetricIdAllocator(address);
- }
- // nullptr and size 0 represent missing value for obfuscated_id
- BytesField obfuscated_id_field(address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
- address.IsEmpty() ? 0 : obfuscated_id.size());
- int ret = stats_write(BLUETOOTH_SOCKET_CONNECTION_STATE_CHANGED, obfuscated_id_field, port, type,
- connection_state, tx_bytes, rx_bytes, uid, server_port, socket_role,
- metric_id, static_cast<int64_t>(connection_duration_ms), error_code,
- is_hardware_offload);
- if (ret < 0) {
- log::warn(
- "failed for {}, port {}, type {}, state {}, tx_bytes {}, rx_bytes {}, "
- "uid {}, server_port {}, socket_role {}, error {}, connection_duration_ms {}, "
- "socket_error_code {}, "
- "is_hardware_offload {}",
- address, port, type, connection_state, tx_bytes, rx_bytes, uid, server_port,
- socket_role, ret, connection_duration_ms, error_code, is_hardware_offload);
- }
-}
-
-void LogManufacturerInfo(const RawAddress& address,
- android::bluetooth::AddressTypeEnum address_type,
- android::bluetooth::DeviceInfoSrcEnum source_type,
- const std::string& source_name, const std::string& manufacturer,
- const std::string& model, const std::string& hardware_version,
- const std::string& software_version) {
- std::string obfuscated_id;
- int metric_id = 0;
- if (!address.IsEmpty()) {
- obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
- metric_id = bluetooth::shim::AllocateIdFromMetricIdAllocator(address);
- }
- // nullptr and size 0 represent missing value for obfuscated_id
- BytesField obfuscated_id_field(address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
- address.IsEmpty() ? 0 : obfuscated_id.size());
- int ret = stats_write(BLUETOOTH_DEVICE_INFO_REPORTED, obfuscated_id_field, source_type,
- source_name.c_str(), manufacturer.c_str(), model.c_str(),
- hardware_version.c_str(), software_version.c_str(), metric_id, address_type,
- address.address[5], address.address[4], address.address[3]);
- if (ret < 0) {
- log::warn(
- "failed for {}, source_type {}, source_name {}, manufacturer {}, model "
- "{}, hardware_version {}, software_version {} MAC address type {} MAC "
- "address prefix {} {} {}, error {}",
- address, source_type, source_name, manufacturer, model, hardware_version,
- software_version, address_type, address.address[5], address.address[4],
- address.address[3], ret);
- }
-}
-
-void LogBluetoothHalCrashReason(const RawAddress& address, uint32_t error_code,
- uint32_t vendor_error_code) {
- std::string obfuscated_id;
- if (!address.IsEmpty()) {
- obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
- }
- // nullptr and size 0 represent missing value for obfuscated_id
- BytesField obfuscated_id_field(address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
- address.IsEmpty() ? 0 : obfuscated_id.size());
- int ret = stats_write(BLUETOOTH_HAL_CRASH_REASON_REPORTED, 0, obfuscated_id_field, error_code,
- vendor_error_code);
- if (ret < 0) {
- log::warn("failed for {}, error_code 0x{:x}, vendor_error_code 0x{:x}, error {}", address,
- error_code, vendor_error_code, ret);
- }
-}
-
-void LogLeAudioConnectionSessionReported(
- int32_t group_size, int32_t group_metric_id, int64_t connection_duration_nanos,
- const std::vector<int64_t>& device_connecting_offset_nanos,
- const std::vector<int64_t>& device_connected_offset_nanos,
- const std::vector<int64_t>& device_connection_duration_nanos,
- const std::vector<int32_t>& device_connection_status,
- const std::vector<int32_t>& device_disconnection_status,
- const std::vector<RawAddress>& device_address,
- const std::vector<int64_t>& streaming_offset_nanos,
- const std::vector<int64_t>& streaming_duration_nanos,
- const std::vector<int32_t>& streaming_context_type) {
- std::vector<int32_t> device_metric_id(device_address.size());
- for (uint64_t i = 0; i < device_address.size(); i++) {
- if (!device_address[i].IsEmpty()) {
- device_metric_id[i] = bluetooth::shim::AllocateIdFromMetricIdAllocator(device_address[i]);
- } else {
- device_metric_id[i] = 0;
- }
- }
- int ret = stats_write(LE_AUDIO_CONNECTION_SESSION_REPORTED, group_size, group_metric_id,
- connection_duration_nanos, device_connecting_offset_nanos,
- device_connected_offset_nanos, device_connection_duration_nanos,
- device_connection_status, device_disconnection_status, device_metric_id,
- streaming_offset_nanos, streaming_duration_nanos, streaming_context_type);
- if (ret < 0) {
- log::warn(
- "failed for group {}device_connecting_offset_nanos[{}], "
- "device_connected_offset_nanos[{}], "
- "device_connection_duration_nanos[{}], device_connection_status[{}], "
- "device_disconnection_status[{}], device_metric_id[{}], "
- "streaming_offset_nanos[{}], streaming_duration_nanos[{}], "
- "streaming_context_type[{}]",
- group_metric_id, device_connecting_offset_nanos.size(),
- device_connected_offset_nanos.size(), device_connection_duration_nanos.size(),
- device_connection_status.size(), device_disconnection_status.size(),
- device_metric_id.size(), streaming_offset_nanos.size(), streaming_duration_nanos.size(),
- streaming_context_type.size());
- }
-}
-
-void LogLeAudioBroadcastSessionReported(int64_t duration_nanos) {
- int ret = stats_write(LE_AUDIO_BROADCAST_SESSION_REPORTED, duration_nanos);
- if (ret < 0) {
- log::warn("failed for duration={}", duration_nanos);
- }
-}
-
-} // namespace common
-
-} // namespace bluetooth
diff --git a/system/common/metrics.h b/system/common/metrics.h
deleted file mode 100644
index 4ccb47f64c..0000000000
--- a/system/common/metrics.h
+++ /dev/null
@@ -1,272 +0,0 @@
-/******************************************************************************
- *
- * Copyright 2016 Google, Inc.
- *
- * 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.
- *
- ******************************************************************************/
-
-#pragma once
-
-#include <bta/include/bta_api.h>
-#include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
-#include <frameworks/proto_logging/stats/enums/bluetooth/hci/enums.pb.h>
-#include <frameworks/proto_logging/stats/enums/bluetooth/le/enums.pb.h>
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "hci/address.h"
-#include "os/metrics.h"
-#include "types/raw_address.h"
-
-namespace bluetooth {
-
-namespace common {
-
-/**
- * Unknown connection handle for metrics purpose
- */
-static const uint32_t kUnknownConnectionHandle = 0xFFFF;
-
-/**
- * Log link layer connection event
- *
- * @param address Stack wide consistent Bluetooth address of this event,
- * nullptr if unknown
- * @param connection_handle connection handle of this event,
- * {@link kUnknownConnectionHandle} if unknown
- * @param direction direction of this connection
- * @param link_type type of the link
- * @param hci_cmd HCI command opecode associated with this event, if any
- * @param hci_event HCI event code associated with this event, if any
- * @param hci_ble_event HCI BLE event code associated with this event, if any
- * @param cmd_status Command status associated with this event, if any
- * @param reason_code Reason code associated with this event, if any
- */
-void LogLinkLayerConnectionEvent(const RawAddress* address, uint32_t connection_handle,
- android::bluetooth::DirectionEnum direction, uint16_t link_type,
- uint32_t hci_cmd, uint16_t hci_event, uint16_t hci_ble_event,
- uint16_t cmd_status, uint16_t reason_code);
-
-/**
- * Logs when Bluetooth controller failed to reply with command status within
- * a timeout period after receiving an HCI command from the host
- *
- * @param hci_cmd opcode of HCI command that caused this timeout
- */
-void LogHciTimeoutEvent(uint32_t hci_cmd);
-
-/**
- * Logs when we receive Bluetooth Read Remote Version Information Complete
- * Event from the remote device, as documented by the Bluetooth Core HCI
- * specification
- *
- * Reference: 5.0 Core Specification, Vol 2, Part E, Page 1118
- *
- * @param handle handle of associated ACL connection
- * @param status HCI command status of this event
- * @param version version code from read remote version complete event
- * @param manufacturer_name manufacturer code from read remote version complete
- * event
- * @param subversion subversion code from read remote version complete event
- */
-void LogRemoteVersionInfo(uint16_t handle, uint8_t status, uint8_t version,
- uint16_t manufacturer_name, uint16_t subversion);
-
-/**
- * Log A2DP audio buffer underrun event
- *
- * @param address A2DP device associated with this event
- * @param encoding_interval_millis encoding interval in milliseconds
- * @param num_missing_pcm_bytes number of PCM bytes that cannot be read from
- * the source
- */
-void LogA2dpAudioUnderrunEvent(const RawAddress& address, uint64_t encoding_interval_millis,
- int num_missing_pcm_bytes);
-
-/**
- * Log A2DP audio buffer overrun event
- *
- * @param address A2DP device associated with this event
- * @param encoding_interval_millis encoding interval in milliseconds
- * @param num_dropped_buffers number of encoded buffers dropped from Tx queue
- * @param num_dropped_encoded_frames number of encoded frames dropped from Tx
- * queue
- * @param num_dropped_encoded_bytes number of encoded bytes dropped from Tx
- * queue
- */
-void LogA2dpAudioOverrunEvent(const RawAddress& address, uint64_t encoding_interval_millis,
- int num_dropped_buffers, int num_dropped_encoded_frames,
- int num_dropped_encoded_bytes);
-
-/**
- * Log A2DP playback state changed event
- *
- * @param address A2DP device associated with this event
- * @param playback_state audio playback state
- * @param audio_coding_mode audio codec encoding mode
- */
-void LogA2dpPlaybackEvent(const RawAddress& address, int playback_state, int audio_coding_mode);
-
-/**
- * Log read RSSI result
- *
- * @param address device associated with this event
- * @param handle connection handle of this event,
- * {@link kUnknownConnectionHandle} if unknown
- * @param cmd_status command status from read RSSI command
- * @param rssi rssi value in dBm
- */
-void LogReadRssiResult(const RawAddress& address, uint16_t handle, uint32_t cmd_status,
- int8_t rssi);
-
-/**
- * Log failed contact counter report
- *
- * @param address device associated with this event
- * @param handle connection handle of this event,
- * {@link kUnknownConnectionHandle} if unknown
- * @param cmd_status command status from read failed contact counter command
- * @param failed_contact_counter Number of consecutive failed contacts for a
- * connection corresponding to the Handle
- */
-void LogReadFailedContactCounterResult(const RawAddress& address, uint16_t handle,
- uint32_t cmd_status, int32_t failed_contact_counter);
-
-/**
- * Log transmit power level for a particular device after read
- *
- * @param address device associated with this event
- * @param handle connection handle of this event,
- * {@link kUnknownConnectionHandle} if unknown
- * @param cmd_status command status from read failed contact counter command
- * @param transmit_power_level transmit power level for connection to this
- * device
- */
-void LogReadTxPowerLevelResult(const RawAddress& address, uint16_t handle, uint32_t cmd_status,
- int32_t transmit_power_level);
-
-/**
- * Logs when there is an event related to Bluetooth Security Manager Protocol
- *
- * @param address address of associated device
- * @param smp_cmd SMP command code associated with this event
- * @param direction direction of this SMP command
- * @param smp_fail_reason SMP pairing failure reason code from SMP spec
- */
-void LogSmpPairingEvent(const RawAddress& address, uint8_t smp_cmd,
- android::bluetooth::DirectionEnum direction, uint8_t smp_fail_reason);
-
-/**
- * Logs there is an event related Bluetooth classic pairing
- *
- * @param address address of associated device
- * @param handle connection handle of this event,
- * {@link kUnknownConnectionHandle} if unknown
- * @param hci_cmd HCI command associated with this event
- * @param hci_event HCI event associated with this event
- * @param cmd_status Command status associated with this event
- * @param reason_code Reason code associated with this event
- * @param event_value A status value related to this specific event
- */
-void LogClassicPairingEvent(const RawAddress& address, uint16_t handle, uint32_t hci_cmd,
- uint16_t hci_event, uint16_t cmd_status, uint16_t reason_code,
- int64_t event_value);
-
-/**
- * Logs when certain Bluetooth SDP attributes are discovered
- *
- * @param address address of associated device
- * @param protocol_uuid 16 bit protocol UUID from Bluetooth Assigned Numbers
- * @param attribute_id 16 bit attribute ID from Bluetooth Assigned Numbers
- * @param attribute_size size of this attribute
- * @param attribute_value pointer to the attribute data, must be larger than
- * attribute_size
- */
-void LogSdpAttribute(const RawAddress& address, uint16_t protocol_uuid, uint16_t attribute_id,
- size_t attribute_size, const char* attribute_value);
-
-/**
- * Logs when there is a change in Bluetooth socket connection state
- *
- * @param address address of associated device, empty if this is a server port
- * @param port port of this socket connection
- * @param type type of socket
- * @param connection_state socket connection state
- * @param tx_bytes number of bytes transmitted
- * @param rx_bytes number of bytes received
- * @param server_port server port of this socket, if any. When both
- * |server_port| and |port| fields are populated, |port| must be spawned
- * by |server_port|
- * @param socket_role role of this socket, server or connection
- * @param uid socket owner's uid
- * @param connection_duration_ms duration of socket connection in milliseconds
- * @param error_code error code of socket failures
- * @param is_hardware_offload whether this is a offload socket
- */
-void LogSocketConnectionState(const RawAddress& address, int port, int type,
- android::bluetooth::SocketConnectionstateEnum connection_state,
- int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port,
- android::bluetooth::SocketRoleEnum socket_role,
- uint64_t connection_duration_ms,
- android::bluetooth::SocketErrorEnum error_code,
- bool is_hardware_offload);
-
-/**
- * Logs when a Bluetooth device's manufacturer information is learnt
- *
- * @param address address of associated device
- * @param source_type where is this device info obtained from
- * @param source_name name of the data source, internal or external
- * @param manufacturer name of the manufacturer of this device
- * @param model model of this device
- * @param hardware_version hardware version of this device
- * @param software_version software version of this device
- */
-void LogManufacturerInfo(const RawAddress& address,
- android::bluetooth::AddressTypeEnum address_type,
- android::bluetooth::DeviceInfoSrcEnum source_type,
- const std::string& source_name, const std::string& manufacturer,
- const std::string& model, const std::string& hardware_version,
- const std::string& software_version);
-
-/**
- * Logs when received Bluetooth HAL crash reason report.
- *
- * @param address current connected address.
- * @param error_code the crash reason from bluetooth hal
- * @param vendor_error_code the vendor crash reason from bluetooth Firmware
- */
-void LogBluetoothHalCrashReason(const RawAddress& address, uint32_t error_code,
- uint32_t vendor_error_code);
-
-void LogLeAudioConnectionSessionReported(
- int32_t group_size, int32_t group_metric_id, int64_t connection_duration_nanos,
- const std::vector<int64_t>& device_connecting_offset_nanos,
- const std::vector<int64_t>& device_connected_offset_nanos,
- const std::vector<int64_t>& device_connection_duration_nanos,
- const std::vector<int32_t>& device_connection_status,
- const std::vector<int32_t>& device_disconnection_status,
- const std::vector<RawAddress>& device_address,
- const std::vector<int64_t>& streaming_offset_nanos,
- const std::vector<int64_t>& streaming_duration_nanos,
- const std::vector<int32_t>& streaming_context_type);
-
-void LogLeAudioBroadcastSessionReported(int64_t duration_nanos);
-
-} // namespace common
-
-} // namespace bluetooth
diff --git a/system/common/metrics_linux.cc b/system/common/metrics_linux.cc
deleted file mode 100644
index 3283619415..0000000000
--- a/system/common/metrics_linux.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-/******************************************************************************
- *
- * Copyright 2018 Google, Inc.
- *
- * 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.
- *
- ******************************************************************************/
-
-#include <bluetooth/log.h>
-
-#include "common/metrics.h"
-#include "types/raw_address.h"
-
-namespace bluetooth {
-
-namespace common {
-
-void LogClassicPairingEvent(const RawAddress& /* address */, uint16_t /* handle */,
- uint32_t /* hci_cmd */, uint16_t /* hci_event */,
- uint16_t /* cmd_status */, uint16_t /* reason_code */,
- int64_t /* event_value */) {}
-
-void LogSocketConnectionState(const RawAddress& /* address */, int /* port */, int /* type */,
- android::bluetooth::SocketConnectionstateEnum /* connection_state */,
- int64_t /* tx_bytes */, int64_t /* rx_bytes */, int /* uid */,
- int /* server_port */,
- android::bluetooth::SocketRoleEnum /* socket_role */,
- uint64_t /* connection_duration_ms */,
- android::bluetooth::SocketErrorEnum /* error_code */,
- bool /* is_hardware_offload */) {}
-
-void LogHciTimeoutEvent(uint32_t /* hci_cmd */) {}
-
-void LogA2dpAudioUnderrunEvent(const RawAddress& /* address */,
- uint64_t /* encoding_interval_millis */,
- int /* num_missing_pcm_bytes */) {}
-
-void LogA2dpAudioOverrunEvent(const RawAddress& /* address */,
- uint64_t /* encoding_interval_millis */,
- int /* num_dropped_buffers */, int /* num_dropped_encoded_frames */,
- int /* num_dropped_encoded_bytes */) {}
-
-void LogA2dpPlaybackEvent(const RawAddress& /* address */, int /* playback_state */,
- int /* audio_coding_mode */) {}
-
-void LogBluetoothHalCrashReason(const RawAddress& /* address */, uint32_t /* error_code */,
- uint32_t /* vendor_error_code */) {}
-
-void LogReadRssiResult(const RawAddress& /* address */, uint16_t /* handle */,
- uint32_t /* cmd_status */, int8_t /* rssi */) {}
-
-void LogReadFailedContactCounterResult(const RawAddress& /* address */, uint16_t /* handle */,
- uint32_t /* cmd_status */,
- int32_t /* failed_contact_counter */) {}
-
-void LogReadTxPowerLevelResult(const RawAddress& /* address */, uint16_t /* handle */,
- uint32_t /* cmd_status */, int32_t /* transmit_power_level */) {}
-
-void LogRemoteVersionInfo(uint16_t /* handle */, uint8_t /* status */, uint8_t /* version */,
- uint16_t /* manufacturer_name */, uint16_t /* subversion */) {}
-
-void LogLinkLayerConnectionEvent(const RawAddress* /* address */, uint32_t /* connection_handle */,
- android::bluetooth::DirectionEnum /* direction */,
- uint16_t /* link_type */, uint32_t /* hci_cmd */,
- uint16_t /* hci_event */, uint16_t /* hci_ble_event */,
- uint16_t /* cmd_status */, uint16_t /* reason_code */) {}
-
-void LogManufacturerInfo(const RawAddress& /* address */,
- android::bluetooth::AddressTypeEnum /* address_type */,
- android::bluetooth::DeviceInfoSrcEnum /* source_type */,
- const std::string& /* source_name */,
- const std::string& /* manufacturer */, const std::string& /* model */,
- const std::string& /* hardware_version */,
- const std::string& /* software_version */) {}
-
-void LogSdpAttribute(const RawAddress& /* address */, uint16_t /* protocol_uuid */,
- uint16_t /* attribute_id */, size_t /* attribute_size */,
- const char* /* attribute_value */) {}
-
-void LogSmpPairingEvent(const RawAddress& /* address */, uint8_t /* smp_cmd */,
- android::bluetooth::DirectionEnum /* direction */,
- uint8_t /* smp_fail_reason */) {}
-
-void LogLeAudioConnectionSessionReported(
- int32_t /* group_size */, int32_t /* group_metric_id */,
- int64_t /* connection_duration_nanos */,
- const std::vector<int64_t>& /* device_connecting_offset_nanos */,
- const std::vector<int64_t>& /* device_connected_offset_nanos */,
- const std::vector<int64_t>& /* device_connection_duration_nanos */,
- const std::vector<int32_t>& /* device_connection_status */,
- const std::vector<int32_t>& /* device_disconnection_status */,
- const std::vector<RawAddress>& /* device_address */,
- const std::vector<int64_t>& /* streaming_offset_nanos */,
- const std::vector<int64_t>& /* streaming_duration_nanos */,
- const std::vector<int32_t>& /* streaming_context_type */) {}
-
-void LogLeAudioBroadcastSessionReported(int64_t /* duration_nanos */) {}
-
-} // namespace common
-
-} // namespace bluetooth
diff --git a/system/conf/interop_database.conf b/system/conf/interop_database.conf
index ecf3da0b07..d921db421d 100644
--- a/system/conf/interop_database.conf
+++ b/system/conf/interop_database.conf
@@ -895,3 +895,8 @@ BSK10 = Name_Based
[INTEROP_DISABLE_HF_PROFILE]
JBL Flip 5 = Name_Based
JBL Flip 6 = Name_Based
+
+# Some devices don't respond to LE appearance read request.
+[INTEROP_DISABLE_READ_LE_APPEARANCE]
+L1_L = Name_Based
+L1_R = Name_Based
diff --git a/system/device/include/interop.h b/system/device/include/interop.h
index 22233bcd65..d72315d1b0 100644
--- a/system/device/include/interop.h
+++ b/system/device/include/interop.h
@@ -358,16 +358,20 @@ typedef enum {
// Peer can request proper latency based on its power state later.
INTEROP_HID_PREF_CONN_ZERO_LATENCY,
- // Some HOGP devices have the report map longer than the maximum GATT attribute value length (512
- // bytes).
+ // Some HOGP devices have the report map longer than the maximum GATT
+ // attribute value length (512 bytes).
INTEROP_HOGP_LONG_REPORT,
- // Some HOGP devices requires MTU exchange be part of the initial setup to function.
+ // Some HOGP devices requires MTU exchange be part of the initial setup to
+ // function.
INTEROP_HOGP_FORCE_MTU_EXCHANGE,
// Some devices claim to support HFP in EIR but does not actually support it.
INTEROP_DISABLE_HF_PROFILE,
+ // Some devices don't respond to LE appearance read request.
+ INTEROP_DISABLE_READ_LE_APPEARANCE,
+
END_OF_INTEROP_LIST
} interop_feature_t;
diff --git a/system/device/src/interop.cc b/system/device/src/interop.cc
index 60d90cf6d6..44313664ed 100644
--- a/system/device/src/interop.cc
+++ b/system/device/src/interop.cc
@@ -392,6 +392,7 @@ static const char* interop_feature_string_(const interop_feature_t feature) {
CASE_RETURN_STR(INTEROP_HOGP_LONG_REPORT);
CASE_RETURN_STR(INTEROP_HOGP_FORCE_MTU_EXCHANGE);
CASE_RETURN_STR(INTEROP_DISABLE_HF_PROFILE);
+ CASE_RETURN_STR(INTEROP_DISABLE_READ_LE_APPEARANCE);
}
return UNKNOWN_INTEROP_FEATURE;
}
diff --git a/system/gd/Android.bp b/system/gd/Android.bp
index 26f31f0b8e..45555f130a 100644
--- a/system/gd/Android.bp
+++ b/system/gd/Android.bp
@@ -194,7 +194,7 @@ cc_library_static {
"packages/modules/Bluetooth/system",
],
apex_available: ["com.android.bt"],
- min_sdk_version: "31",
+ min_sdk_version: "33",
static_libs: [
"bluetooth_flags_c_lib",
"libchrome",
@@ -357,8 +357,8 @@ cc_test {
srcs: [
":BluetoothPacketTestSources",
":TestCommonMockFunctions",
+ ":TestMockMainShim",
":TestMockMainShimEntry",
- ":TestMockStackMetrics",
"common/bidi_queue_unittest.cc",
"common/blocking_queue_unittest.cc",
"common/byte_array_test.cc",
@@ -414,6 +414,9 @@ cc_test {
"storage/mutation_test.cc",
"storage/storage_module_test.cc",
],
+ cflags: [
+ "-DUSE_FAKE_TIMERS",
+ ],
static_libs: [
"bluetooth_flags_c_lib_for_test",
"libbase",
@@ -581,11 +584,12 @@ cc_fuzz {
defaults: ["gd_fuzz_defaults"],
srcs: [
":TestCommonMockFunctions",
- ":TestMockStackMetrics",
+ ":TestMockMainShim",
"hci/fuzz/acl_manager_fuzz_test.cc",
],
include_dirs: [
"packages/modules/Bluetooth/system",
+ "packages/modules/Bluetooth/system/include",
],
static_libs: [
"libbt-platform-protos-lite",
diff --git a/system/gd/common/audit_log.cc b/system/gd/common/audit_log.cc
index e83c2894f8..2e112a0c34 100644
--- a/system/gd/common/audit_log.cc
+++ b/system/gd/common/audit_log.cc
@@ -16,6 +16,8 @@
#include "common/audit_log.h"
+#include <format>
+
#ifdef __ANDROID__
#include <log/log_event_list.h>
#endif // __ANDROID__
@@ -43,8 +45,8 @@ void LogConnectionAdminAuditEvent([[maybe_unused]] const char* action,
android_log_event_list(SEC_TAG_BLUETOOTH_CONNECTION)
<< address.ToRedactedStringForLogging()
- << /* success */ int32_t(status == hci::ErrorCode::SUCCESS) << action << ": "
- << ErrorCodeText(status) << LOG_ID_SECURITY;
+ << /* success */ int32_t(status == hci::ErrorCode::SUCCESS)
+ << std::format("{}: {}", action, ErrorCodeText(status)) << LOG_ID_SECURITY;
#endif /* defined(__ANDROID__) && !defined (FUZZ_TARGET) */
}
diff --git a/system/gd/hal/hci_hal.h b/system/gd/hal/hci_hal.h
index 49f007ba55..2c028c3b6f 100644
--- a/system/gd/hal/hci_hal.h
+++ b/system/gd/hal/hci_hal.h
@@ -51,6 +51,10 @@ public:
// Send an ISO data packet from the controller to the host
// @param data the ISO HCI packet to be passed to the host stack
virtual void isoDataReceived(HciPacket data) = 0;
+
+ // This function is invoked when the controller encounters an error requiring
+ // the Bluetooth stack to initiate a reset.
+ virtual void controllerNeedsReset() {}
};
// Mirrors hardware/interfaces/bluetooth/1.0/IBluetoothHci.hal in Android
@@ -101,9 +105,6 @@ public:
// Get the MSFT opcode (as specified in Microsoft-defined Bluetooth HCI
// extensions)
virtual uint16_t getMsftOpcode() { return 0; }
-
- // Mark the controller as broken to prevent further read / write operation.
- virtual void markControllerBroken() { return; }
};
// LINT.ThenChange(fuzz/fuzz_hci_hal.h)
diff --git a/system/gd/hal/hci_hal_android_test.cc b/system/gd/hal/hci_hal_android_test.cc
index 247f15745f..f128f508cf 100644
--- a/system/gd/hal/hci_hal_android_test.cc
+++ b/system/gd/hal/hci_hal_android_test.cc
@@ -20,6 +20,7 @@
#include <queue>
#include <thread>
+#include "com_android_bluetooth_flags.h"
#include "hal/hci_backend.h"
#include "hal/hci_hal.h"
#include "os/thread.h"
@@ -79,10 +80,13 @@ protected:
}
void TearDown() override {
- fake_registry_.StopAll();
handler_->Clear();
- delete thread_;
+ if (com::android::bluetooth::flags::same_handler_for_all_modules()) {
+ handler_->WaitUntilStopped(bluetooth::kHandlerStopTimeout);
+ }
+ fake_registry_.StopAll();
delete handler_;
+ delete thread_;
}
HciHal* hal;
diff --git a/system/gd/hal/hci_hal_host.cc b/system/gd/hal/hci_hal_host.cc
index f441fcf212..bf020a2e02 100644
--- a/system/gd/hal/hci_hal_host.cc
+++ b/system/gd/hal/hci_hal_host.cc
@@ -262,9 +262,6 @@ public:
void sendHciCommand(HciPacket command) override {
std::lock_guard<std::mutex> lock(api_mutex_);
- if (controller_broken_) {
- return;
- }
log::assert_that(sock_fd_ != INVALID_FD, "assert failed: sock_fd_ != INVALID_FD");
std::vector<uint8_t> packet = std::move(command);
btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING,
@@ -275,9 +272,6 @@ public:
void sendAclData(HciPacket data) override {
std::lock_guard<std::mutex> lock(api_mutex_);
- if (controller_broken_) {
- return;
- }
log::assert_that(sock_fd_ != INVALID_FD, "assert failed: sock_fd_ != INVALID_FD");
std::vector<uint8_t> packet = std::move(data);
btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING,
@@ -288,10 +282,6 @@ public:
void sendScoData(HciPacket data) override {
std::lock_guard<std::mutex> lock(api_mutex_);
- if (controller_broken_) {
- return;
- }
-
log::assert_that(sock_fd_ != INVALID_FD, "assert failed: sock_fd_ != INVALID_FD");
std::vector<uint8_t> packet = std::move(data);
btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING,
@@ -302,9 +292,6 @@ public:
void sendIsoData(HciPacket data) override {
std::lock_guard<std::mutex> lock(api_mutex_);
- if (controller_broken_) {
- return;
- }
log::assert_that(sock_fd_ != INVALID_FD, "assert failed: sock_fd_ != INVALID_FD");
std::vector<uint8_t> packet = std::move(data);
btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING,
@@ -317,15 +304,6 @@ public:
return os::Management::getInstance().getVendorSpecificCode(MGMT_VS_OPCODE_MSFT);
}
- void markControllerBroken() override {
- std::lock_guard<std::mutex> lock(api_mutex_);
- if (controller_broken_) {
- log::error("Controller already marked as broken!");
- return;
- }
- controller_broken_ = true;
- }
-
protected:
void ListDependencies(ModuleList* list) const { list->add<LinkClocker>(); }
@@ -337,8 +315,7 @@ protected:
// We don't want to crash when the chipset is broken.
if (sock_fd_ == INVALID_FD) {
log::error("Failed to connect to HCI socket. Aborting HAL initialization process.");
- controller_broken_ = true;
- kill(getpid(), SIGTERM);
+ incoming_packet_callback_->controllerNeedsReset();
return;
}
@@ -392,7 +369,6 @@ private:
std::queue<std::vector<uint8_t>> hci_outgoing_queue_;
SnoopLogger* btsnoop_logger_ = nullptr;
LinkClocker* link_clocker_ = nullptr;
- bool controller_broken_ = false;
void write_to_fd(HciPacket packet) {
// TODO(chromeos-bt-team@): replace this with new queue when it's ready
@@ -414,8 +390,8 @@ private:
hci_outgoing_queue_.pop();
if (bytes_written == -1) {
log::error("Can't write to socket: {}", strerror(errno));
- markControllerBroken();
- kill(getpid(), SIGTERM);
+ incoming_packet_callback_->controllerNeedsReset();
+ return;
}
if (hci_outgoing_queue_.empty()) {
hci_incoming_thread_.GetReactor()->ModifyRegistration(reactable_,
@@ -439,15 +415,13 @@ private:
// we don't want crash when the chipset is broken.
if (received_size == -1) {
log::error("Can't receive from socket: {}", strerror(errno));
- markControllerBroken();
- kill(getpid(), SIGTERM);
+ incoming_packet_callback_->controllerNeedsReset();
return;
}
if (received_size == 0) {
log::warn("Can't read H4 header. EOF received");
- markControllerBroken();
- kill(getpid(), SIGTERM);
+ incoming_packet_callback_->controllerNeedsReset();
return;
}
diff --git a/system/gd/hal/hci_hal_host_test.cc b/system/gd/hal/hci_hal_host_test.cc
index 4f4c6bc6d0..d4539d6c3b 100644
--- a/system/gd/hal/hci_hal_host_test.cc
+++ b/system/gd/hal/hci_hal_host_test.cc
@@ -32,6 +32,7 @@
#include <utility>
#include <vector>
+#include "com_android_bluetooth_flags.h"
#include "hal/hci_hal.h"
#include "hal/serialize_packet.h"
#include "os/thread.h"
@@ -155,12 +156,15 @@ protected:
void TearDown() override {
hal_->unregisterIncomingPacketCallback();
+ handler_->Clear();
+ if (com::android::bluetooth::flags::same_handler_for_all_modules()) {
+ handler_->WaitUntilStopped(bluetooth::kHandlerStopTimeout);
+ }
fake_registry_.StopAll();
+ delete handler_;
close(fake_server_socket_);
- handler_->Clear();
delete fake_server_;
delete thread_;
- delete handler_;
}
void SetFakeServerSocketToBlocking() {
diff --git a/system/gd/hal/snoop_logger.h b/system/gd/hal/snoop_logger.h
index b009add89c..b0783442b3 100644
--- a/system/gd/hal/snoop_logger.h
+++ b/system/gd/hal/snoop_logger.h
@@ -17,6 +17,7 @@
#pragma once
#include <bluetooth/log.h>
+#include <com_android_bluetooth_flags.h>
#include <fstream>
#include <string>
@@ -195,6 +196,13 @@ public:
};
SnoopLogger(os::Handler* handler);
+ ~SnoopLogger() {
+ if (!com::android::bluetooth::flags::same_handler_for_all_modules()) {
+ GetHandler()->Clear();
+ GetHandler()->WaitUntilStopped(std::chrono::milliseconds(2000));
+ delete GetHandler();
+ }
+ }
// Returns the maximum number of packets per file
// Changes to this value is only effective after restarting Bluetooth
diff --git a/system/gd/hci/acl_manager.cc b/system/gd/hci/acl_manager.cc
index 73f455f168..280cc237b4 100644
--- a/system/gd/hci/acl_manager.cc
+++ b/system/gd/hci/acl_manager.cc
@@ -260,21 +260,6 @@ void AclManager::CreateLeConnection(AddressWithType address_with_type, bool is_d
CallOn(pimpl_->le_impl_, &le_impl::create_le_connection, address_with_type, true, is_direct);
}
-void AclManager::IsOnBackgroundList(AddressWithType address_with_type, std::promise<bool> promise) {
- CallOn(pimpl_->le_impl_, &le_impl::is_on_background_connection_list, address_with_type,
- std::move(promise));
-}
-
-void AclManager::SetLeSuggestedDefaultDataParameters(uint16_t octets, uint16_t time) {
- CallOn(pimpl_->le_impl_, &le_impl::set_le_suggested_default_data_parameters, octets, time);
-}
-
-void AclManager::LeSetDefaultSubrate(uint16_t subrate_min, uint16_t subrate_max,
- uint16_t max_latency, uint16_t cont_num, uint16_t sup_tout) {
- CallOn(pimpl_->le_impl_, &le_impl::LeSetDefaultSubrate, subrate_min, subrate_max, max_latency,
- cont_num, sup_tout);
-}
-
void AclManager::SetPrivacyPolicyForInitiatorAddress(
LeAddressManager::AddressPolicy address_policy, AddressWithType fixed_address,
std::chrono::milliseconds minimum_rotation_time,
diff --git a/system/gd/hci/acl_manager.h b/system/gd/hci/acl_manager.h
index b6932eee52..f38f1ff689 100644
--- a/system/gd/hci/acl_manager.h
+++ b/system/gd/hci/acl_manager.h
@@ -86,12 +86,6 @@ public:
// Generates OnLeConnectSuccess if connected, or OnLeConnectFail otherwise
virtual void CreateLeConnection(AddressWithType address_with_type, bool is_direct);
- // Ask the controller for specific data parameters
- virtual void SetLeSuggestedDefaultDataParameters(uint16_t octets, uint16_t time);
-
- virtual void LeSetDefaultSubrate(uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency,
- uint16_t cont_num, uint16_t sup_tout);
-
virtual void SetPrivacyPolicyForInitiatorAddress(LeAddressManager::AddressPolicy address_policy,
AddressWithType fixed_address,
std::chrono::milliseconds minimum_rotation_time,
@@ -108,7 +102,6 @@ public:
// connected
virtual void CancelConnect(Address address);
virtual void RemoveFromBackgroundList(AddressWithType address_with_type);
- virtual void IsOnBackgroundList(AddressWithType address_with_type, std::promise<bool> promise);
virtual void CancelLeConnect(AddressWithType address_with_type);
diff --git a/system/gd/hci/acl_manager/le_impl.h b/system/gd/hci/acl_manager/le_impl.h
index a6761e38b7..122f76525e 100644
--- a/system/gd/hci/acl_manager/le_impl.h
+++ b/system/gd/hci/acl_manager/le_impl.h
@@ -39,11 +39,11 @@
#include "hci/hci_packets.h"
#include "hci/le_address_manager.h"
#include "macros.h"
+#include "main/shim/metrics_api.h"
#include "os/alarm.h"
#include "os/handler.h"
#include "os/system_properties.h"
#include "stack/include/btm_ble_api_types.h"
-#include "stack/include/stack_metrics_logging.h"
namespace bluetooth {
namespace hci {
@@ -426,7 +426,7 @@ public:
return;
}
- log_le_connection_status(address, true /* is_connect */, status);
+ bluetooth::shim::LogMetricLeConnectionStatus(address, true /* is_connect */, status);
const bool in_filter_accept_list = is_device_in_accept_list(remote_address);
@@ -586,7 +586,8 @@ public:
arm_on_resume_ = true;
add_device_to_accept_list(remote_address);
}
- log_le_connection_status(remote_address.GetAddress(), false /* is_connect */, reason);
+ bluetooth::shim::LogMetricLeConnectionStatus(remote_address.GetAddress(),
+ false /* is_connect */, reason);
}
void on_le_connection_update_complete(LeMetaEventView view) {
@@ -724,7 +725,8 @@ public:
}
void add_device_to_accept_list(AddressWithType address_with_type) {
- log_le_device_in_accept_list(address_with_type.GetAddress(), true /* is_add */);
+ bluetooth::shim::LogMetricLeDeviceInAcceptList(address_with_type.GetAddress(),
+ true /* is_add */);
if (connections.alreadyConnected(address_with_type)) {
log::info("Device already connected, return");
return;
@@ -747,7 +749,8 @@ public:
}
void remove_device_from_accept_list(AddressWithType address_with_type) {
- log_le_device_in_accept_list(address_with_type.GetAddress(), false /* is_add */);
+ bluetooth::shim::LogMetricLeDeviceInAcceptList(address_with_type.GetAddress(),
+ false /* is_add */);
if (accept_list.find(address_with_type) == accept_list.end()) {
log::warn("Device not in acceptlist and cannot be removed: {}", address_with_type);
return;
@@ -1060,15 +1063,12 @@ public:
add_device_to_accept_list(address_with_type);
}
- if (com::android::bluetooth::flags::
- improve_create_connection_for_already_connecting_device()) {
- bool in_accept_list_due_to_direct_connect =
- direct_connections_.find(address_with_type) != direct_connections_.end();
+ bool in_accept_list_due_to_direct_connect =
+ direct_connections_.find(address_with_type) != direct_connections_.end();
- if (already_in_accept_list && (in_accept_list_due_to_direct_connect || !is_direct)) {
- log::info("Device {} already in accept list. Stop here.", address_with_type);
- return;
- }
+ if (already_in_accept_list && (in_accept_list_due_to_direct_connect || !is_direct)) {
+ log::info("Device {} already in accept list. Stop here.", address_with_type);
+ return;
}
if (is_direct) {
@@ -1132,8 +1132,9 @@ public:
remove_device_from_accept_list(address_with_type);
}
// Temporary mapping the error code to PAGE_TIMEOUT
- log_le_connection_completion(address_with_type.GetAddress(), ErrorCode::PAGE_TIMEOUT,
- true /* is locally initiated */);
+ bluetooth::shim::LogMetricLeConnectionCompletion(address_with_type.GetAddress(),
+ ErrorCode::PAGE_TIMEOUT,
+ true /* is locally initiated */);
le_client_handler_->Post(common::BindOnce(
&LeConnectionCallbacks::OnLeConnectFail, common::Unretained(le_client_callbacks_),
address_with_type, ErrorCode::CONNECTION_ACCEPT_TIMEOUT));
@@ -1145,25 +1146,6 @@ public:
remove_device_from_accept_list(address_with_type);
}
- void set_le_suggested_default_data_parameters(uint16_t length, uint16_t time) {
- auto packet = LeWriteSuggestedDefaultDataLengthBuilder::Create(length, time);
- le_acl_connection_interface_->EnqueueCommand(
- std::move(packet), handler_->BindOnce([](CommandCompleteView /* complete */) {}));
- }
-
- void LeSetDefaultSubrate(uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency,
- uint16_t cont_num, uint16_t sup_tout) {
- le_acl_connection_interface_->EnqueueCommand(
- LeSetDefaultSubrateBuilder::Create(subrate_min, subrate_max, max_latency, cont_num,
- sup_tout),
- handler_->BindOnce([](CommandCompleteView complete) {
- auto complete_view = LeSetDefaultSubrateCompleteView::Create(complete);
- log::assert_that(complete_view.IsValid(), "assert failed: complete_view.IsValid()");
- ErrorCode status = complete_view.GetStatus();
- log::assert_that(status == ErrorCode::SUCCESS, "Status = {}", ErrorCodeText(status));
- }));
- }
-
void clear_resolving_list() { le_address_manager_->ClearResolvingList(); }
void set_privacy_policy_for_initiator_address(LeAddressManager::AddressPolicy address_policy,
@@ -1249,12 +1231,6 @@ public:
background_connections_.erase(address_with_type);
}
- void is_on_background_connection_list(AddressWithType address_with_type,
- std::promise<bool> promise) {
- promise.set_value(background_connections_.find(address_with_type) !=
- background_connections_.end());
- }
-
void OnPause() override { // bluetooth::hci::LeAddressManagerCallback
if (!address_manager_registered) {
log::warn("Unregistered!");
diff --git a/system/gd/hci/acl_manager/le_impl_test.cc b/system/gd/hci/acl_manager/le_impl_test.cc
index 66bc16bbd8..f54d316d30 100644
--- a/system/gd/hci/acl_manager/le_impl_test.cc
+++ b/system/gd/hci/acl_manager/le_impl_test.cc
@@ -284,164 +284,6 @@ protected:
hci_layer_->IncomingEvent(LeSetRandomAddressCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
}
- void test_direct_connection_after_background_connection() {
- set_random_device_address_policy();
-
- hci::AddressWithType address({0x21, 0x22, 0x23, 0x24, 0x25, 0x26},
- AddressType::PUBLIC_DEVICE_ADDRESS);
-
- // arrange: Create background connection. Remember that acl_manager adds device background list
- le_impl_->add_device_to_background_connection_list(address);
- le_impl_->create_le_connection(address, true, /* is_direct */ false);
- hci_layer_->GetCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST);
- hci_layer_->IncomingEvent(
- LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
- auto raw_bg_create_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION);
- hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01));
- sync_handler();
-
- // act: Create direct connection
- le_impl_->create_le_connection(address, true, /* is_direct */ true);
- auto cancel_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION_CANCEL);
- if (cancel_connection.IsValid()) {
- hci_layer_->IncomingEvent(
- LeCreateConnectionCancelCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
- hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create(
- ErrorCode::UNKNOWN_CONNECTION, kHciHandle, Role::CENTRAL,
- AddressType::PUBLIC_DEVICE_ADDRESS, Address::kEmpty, 0x0000, 0x0000, 0x0000,
- ClockAccuracy::PPM_30));
- }
- auto raw_direct_create_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION);
-
- // assert
- auto bg_create_connection =
- LeCreateConnectionView::Create(LeConnectionManagementCommandView::Create(
- AclCommandView::Create(raw_bg_create_connection)));
- EXPECT_TRUE(bg_create_connection.IsValid());
- auto direct_create_connection =
- LeCreateConnectionView::Create(LeConnectionManagementCommandView::Create(
- AclCommandView::Create(raw_direct_create_connection)));
- EXPECT_TRUE(direct_create_connection.IsValid());
- log::info("Scan Interval {}", direct_create_connection.GetLeScanInterval());
- ASSERT_NE(direct_create_connection.GetLeScanInterval(),
- bg_create_connection.GetLeScanInterval());
-
- hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01));
- sync_handler();
-
- // Check state is ARMED
- ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_);
-
- // Simulate timeout on direct connect. Verify background connect is still in place
- EXPECT_CALL(mock_le_connection_callbacks_,
- OnLeConnectFail(_, ErrorCode::CONNECTION_ACCEPT_TIMEOUT))
- .Times(1);
- le_impl_->on_create_connection_timeout(address);
- sync_handler();
- cancel_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION_CANCEL);
- hci_layer_->IncomingEvent(
- LeCreateConnectionCancelCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
- hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create(
- ErrorCode::UNKNOWN_CONNECTION, kHciHandle, Role::CENTRAL,
- AddressType::PUBLIC_DEVICE_ADDRESS, Address::kEmpty, 0x0000, 0x0000, 0x0000,
- ClockAccuracy::PPM_30));
- EXPECT_TRUE(cancel_connection.IsValid());
- raw_bg_create_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION);
- bg_create_connection = LeCreateConnectionView::Create(LeConnectionManagementCommandView::Create(
- AclCommandView::Create(raw_bg_create_connection)));
- EXPECT_TRUE(bg_create_connection.IsValid());
- sync_handler();
- ASSERT_TRUE(le_impl_->create_connection_timeout_alarms_.empty());
-
- hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01));
- sync_handler();
-
- // Check state is ARMED
- ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_);
- }
-
- void test_direct_connect_after_direct_connect() {
- set_random_device_address_policy();
-
- hci::AddressWithType address({0x21, 0x22, 0x23, 0x24, 0x25, 0x26},
- AddressType::PUBLIC_DEVICE_ADDRESS);
-
- // Create first direct connection
- le_impl_->create_le_connection(address, true, /* is_direct */ true);
- hci_layer_->GetCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST);
- hci_layer_->IncomingEvent(
- LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
- auto raw_direct_1_create_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION);
- hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01));
- sync_handler();
-
- // Check state is ARMED
- ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_);
-
- // assert
- auto direct_1_create_connection =
- LeCreateConnectionView::Create(LeConnectionManagementCommandView::Create(
- AclCommandView::Create(raw_direct_1_create_connection)));
- EXPECT_TRUE(direct_1_create_connection.IsValid());
-
- log::info("Second direct connect to the same device");
-
- // Create second direct connection
- le_impl_->create_le_connection(address, true, /* is_direct */ true);
- sync_handler();
-
- CommandView cancel_connection = CommandView::Create(
- PacketView<packet::kLittleEndian>(std::make_shared<std::vector<uint8_t>>()));
-
- if (!com::android::bluetooth::flags::
- improve_create_connection_for_already_connecting_device()) {
- cancel_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION_CANCEL);
- if (cancel_connection.IsValid()) {
- hci_layer_->IncomingEvent(
- LeCreateConnectionCancelCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
- hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create(
- ErrorCode::UNKNOWN_CONNECTION, kHciHandle, Role::CENTRAL,
- AddressType::PUBLIC_DEVICE_ADDRESS, Address::kEmpty, 0x0000, 0x0000, 0x0000,
- ClockAccuracy::PPM_30));
- }
-
- auto raw_direct_2_create_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION);
-
- auto direct_2_create_connection =
- LeCreateConnectionView::Create(LeConnectionManagementCommandView::Create(
- AclCommandView::Create(raw_direct_2_create_connection)));
- EXPECT_TRUE(direct_2_create_connection.IsValid());
- hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01));
- sync_handler();
- } else {
- hci_layer_->AssertNoQueuedCommand();
- }
-
- log::info("Simulate timeout");
-
- EXPECT_CALL(mock_le_connection_callbacks_,
- OnLeConnectFail(_, ErrorCode::CONNECTION_ACCEPT_TIMEOUT))
- .Times(1);
- le_impl_->on_create_connection_timeout(address);
- sync_handler();
- cancel_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION_CANCEL);
- EXPECT_TRUE(cancel_connection.IsValid());
- hci_layer_->IncomingEvent(
- LeCreateConnectionCancelCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
- hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create(
- ErrorCode::UNKNOWN_CONNECTION, kHciHandle, Role::CENTRAL,
- AddressType::PUBLIC_DEVICE_ADDRESS, Address::kEmpty, 0x0000, 0x0000, 0x0000,
- ClockAccuracy::PPM_30));
- sync_handler();
- ASSERT_TRUE(le_impl_->create_connection_timeout_alarms_.empty());
-
- hci_layer_->GetCommand(OpCode::LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST);
- hci_layer_->IncomingEvent(
- LeRemoveDeviceFromFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
- hci_layer_->AssertNoQueuedCommand();
- ASSERT_EQ(ConnectabilityState::DISARMED, le_impl_->connectability_state_);
- }
-
// Need to store the LeAclConnection so it is not immediately dropped => disconnected
std::unique_ptr<LeAclConnection> create_enhanced_connection(std::string remote_address_string,
int handle) {
@@ -1475,29 +1317,6 @@ TEST_F(LeImplTest, cancel_connect) {
ASSERT_TRUE(le_impl_->create_connection_timeout_alarms_.empty());
}
-TEST_F(LeImplTest, set_le_suggested_default_data_parameters) {
- le_impl_->set_le_suggested_default_data_parameters(kLength, kTime);
- sync_handler();
- auto view = CreateLeConnectionManagementCommandView<LeWriteSuggestedDefaultDataLengthView>(
- hci_layer_->GetCommand());
- ASSERT_TRUE(view.IsValid());
- ASSERT_EQ(kLength, view.GetTxOctets());
- ASSERT_EQ(kTime, view.GetTxTime());
-}
-
-TEST_F(LeImplTest, LeSetDefaultSubrate) {
- le_impl_->LeSetDefaultSubrate(kIntervalMin, kIntervalMax, kLatency, kContinuationNumber,
- kTimeout);
- sync_handler();
- auto view = CreateAclCommandView<LeSetDefaultSubrateView>(hci_layer_->GetCommand());
- ASSERT_TRUE(view.IsValid());
- ASSERT_EQ(kIntervalMin, view.GetSubrateMin());
- ASSERT_EQ(kIntervalMax, view.GetSubrateMax());
- ASSERT_EQ(kLatency, view.GetMaxLatency());
- ASSERT_EQ(kContinuationNumber, view.GetContinuationNumber());
- ASSERT_EQ(kTimeout, view.GetSupervisionTimeout());
-}
-
enum class ConnectionCompleteType { CONNECTION_COMPLETE, ENHANCED_CONNECTION_COMPLETE };
class LeImplTestParameterizedByConnectionCompleteEventType
@@ -1716,29 +1535,138 @@ TEST_F(LeImplTest, DisconnectionAcceptlistCallback) {
}
TEST_F(LeImplTest, direct_connection_after_background_connection) {
- // TODO b/356593752 - remove when test removing flag
- com::android::bluetooth::flags::provider_
- ->improve_create_connection_for_already_connecting_device(false);
- test_direct_connection_after_background_connection();
-}
+ set_random_device_address_policy();
+
+ hci::AddressWithType address({0x21, 0x22, 0x23, 0x24, 0x25, 0x26},
+ AddressType::PUBLIC_DEVICE_ADDRESS);
+
+ // arrange: Create background connection. Remember that acl_manager adds device background list
+ le_impl_->add_device_to_background_connection_list(address);
+ le_impl_->create_le_connection(address, true, /* is_direct */ false);
+ hci_layer_->GetCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST);
+ hci_layer_->IncomingEvent(
+ LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
+ auto raw_bg_create_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION);
+ hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01));
+ sync_handler();
+
+ // act: Create direct connection
+ le_impl_->create_le_connection(address, true, /* is_direct */ true);
+ auto cancel_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION_CANCEL);
+ if (cancel_connection.IsValid()) {
+ hci_layer_->IncomingEvent(
+ LeCreateConnectionCancelCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
+ hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create(
+ ErrorCode::UNKNOWN_CONNECTION, kHciHandle, Role::CENTRAL,
+ AddressType::PUBLIC_DEVICE_ADDRESS, Address::kEmpty, 0x0000, 0x0000, 0x0000,
+ ClockAccuracy::PPM_30));
+ }
+ auto raw_direct_create_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION);
+
+ // assert
+ auto bg_create_connection =
+ LeCreateConnectionView::Create(LeConnectionManagementCommandView::Create(
+ AclCommandView::Create(raw_bg_create_connection)));
+ EXPECT_TRUE(bg_create_connection.IsValid());
+ auto direct_create_connection =
+ LeCreateConnectionView::Create(LeConnectionManagementCommandView::Create(
+ AclCommandView::Create(raw_direct_create_connection)));
+ EXPECT_TRUE(direct_create_connection.IsValid());
+ log::info("Scan Interval {}", direct_create_connection.GetLeScanInterval());
+ ASSERT_NE(direct_create_connection.GetLeScanInterval(), bg_create_connection.GetLeScanInterval());
-TEST_F(LeImplTest, direct_connection_after_background_connection_with_improvement) {
- com::android::bluetooth::flags::provider_
- ->improve_create_connection_for_already_connecting_device(true);
- test_direct_connection_after_background_connection();
+ hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01));
+ sync_handler();
+
+ // Check state is ARMED
+ ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_);
+
+ // Simulate timeout on direct connect. Verify background connect is still in place
+ EXPECT_CALL(mock_le_connection_callbacks_,
+ OnLeConnectFail(_, ErrorCode::CONNECTION_ACCEPT_TIMEOUT))
+ .Times(1);
+ le_impl_->on_create_connection_timeout(address);
+ sync_handler();
+ cancel_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION_CANCEL);
+ hci_layer_->IncomingEvent(
+ LeCreateConnectionCancelCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
+ hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create(
+ ErrorCode::UNKNOWN_CONNECTION, kHciHandle, Role::CENTRAL,
+ AddressType::PUBLIC_DEVICE_ADDRESS, Address::kEmpty, 0x0000, 0x0000, 0x0000,
+ ClockAccuracy::PPM_30));
+ EXPECT_TRUE(cancel_connection.IsValid());
+ raw_bg_create_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION);
+ bg_create_connection = LeCreateConnectionView::Create(LeConnectionManagementCommandView::Create(
+ AclCommandView::Create(raw_bg_create_connection)));
+ EXPECT_TRUE(bg_create_connection.IsValid());
+ sync_handler();
+ ASSERT_TRUE(le_impl_->create_connection_timeout_alarms_.empty());
+
+ hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01));
+ sync_handler();
+
+ // Check state is ARMED
+ ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_);
}
TEST_F(LeImplTest, direct_connection_after_direct_connection) {
- // TODO b/356593752 - remove when test removing flag
- com::android::bluetooth::flags::provider_
- ->improve_create_connection_for_already_connecting_device(false);
- test_direct_connect_after_direct_connect();
-}
+ set_random_device_address_policy();
-TEST_F(LeImplTest, direct_connection_after_direct_connection_with_improvement) {
- com::android::bluetooth::flags::provider_
- ->improve_create_connection_for_already_connecting_device(true);
- test_direct_connect_after_direct_connect();
+ hci::AddressWithType address({0x21, 0x22, 0x23, 0x24, 0x25, 0x26},
+ AddressType::PUBLIC_DEVICE_ADDRESS);
+
+ // Create first direct connection
+ le_impl_->create_le_connection(address, true, /* is_direct */ true);
+ hci_layer_->GetCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST);
+ hci_layer_->IncomingEvent(
+ LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
+ auto raw_direct_1_create_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION);
+ hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01));
+ sync_handler();
+
+ // Check state is ARMED
+ ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_);
+
+ // assert
+ auto direct_1_create_connection =
+ LeCreateConnectionView::Create(LeConnectionManagementCommandView::Create(
+ AclCommandView::Create(raw_direct_1_create_connection)));
+ EXPECT_TRUE(direct_1_create_connection.IsValid());
+
+ log::info("Second direct connect to the same device");
+
+ // Create second direct connection
+ le_impl_->create_le_connection(address, true, /* is_direct */ true);
+ sync_handler();
+
+ CommandView cancel_connection = CommandView::Create(
+ PacketView<packet::kLittleEndian>(std::make_shared<std::vector<uint8_t>>()));
+
+ hci_layer_->AssertNoQueuedCommand();
+
+ log::info("Simulate timeout");
+
+ EXPECT_CALL(mock_le_connection_callbacks_,
+ OnLeConnectFail(_, ErrorCode::CONNECTION_ACCEPT_TIMEOUT))
+ .Times(1);
+ le_impl_->on_create_connection_timeout(address);
+ sync_handler();
+ cancel_connection = hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION_CANCEL);
+ EXPECT_TRUE(cancel_connection.IsValid());
+ hci_layer_->IncomingEvent(
+ LeCreateConnectionCancelCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
+ hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create(
+ ErrorCode::UNKNOWN_CONNECTION, kHciHandle, Role::CENTRAL,
+ AddressType::PUBLIC_DEVICE_ADDRESS, Address::kEmpty, 0x0000, 0x0000, 0x0000,
+ ClockAccuracy::PPM_30));
+ sync_handler();
+ ASSERT_TRUE(le_impl_->create_connection_timeout_alarms_.empty());
+
+ hci_layer_->GetCommand(OpCode::LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST);
+ hci_layer_->IncomingEvent(
+ LeRemoveDeviceFromFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS));
+ hci_layer_->AssertNoQueuedCommand();
+ ASSERT_EQ(ConnectabilityState::DISARMED, le_impl_->connectability_state_);
}
TEST_F(LeImplTest, direct_connection_cancel_but_connected) {
diff --git a/system/gd/hci/acl_manager/round_robin_scheduler.cc b/system/gd/hci/acl_manager/round_robin_scheduler.cc
index ad0e6dc621..89897a82e5 100644
--- a/system/gd/hci/acl_manager/round_robin_scheduler.cc
+++ b/system/gd/hci/acl_manager/round_robin_scheduler.cc
@@ -17,7 +17,6 @@
#include "hci/acl_manager/round_robin_scheduler.h"
#include <bluetooth/log.h>
-#include <com_android_bluetooth_flags.h>
#include <memory>
#include <utility>
@@ -65,10 +64,8 @@ void RoundRobinScheduler::Unregister(uint16_t handle) {
log::assert_that(acl_queue_handlers_.count(handle) == 1,
"assert failed: acl_queue_handlers_.count(handle) == 1");
- if (com::android::bluetooth::flags::drop_acl_fragment_on_disconnect()) {
- // Drop the pending fragments and recalculate number_of_sent_packets_
- drop_packet_fragments(handle);
- }
+ // Drop the pending fragments and recalculate number_of_sent_packets_
+ drop_packet_fragments(handle);
auto& acl_queue_handler = acl_queue_handlers_.find(handle)->second;
log::info("unregistering acl_queue handle={}, sent_packets={}", handle,
@@ -94,8 +91,7 @@ void RoundRobinScheduler::Unregister(uint16_t handle) {
starting_point_ = acl_queue_handlers_.begin();
// Restart sending packets if we got acl credits
- if (com::android::bluetooth::flags::drop_acl_fragment_on_disconnect() &&
- credits_reclaimed_from_zero) {
+ if (credits_reclaimed_from_zero) {
start_round_robin();
}
}
diff --git a/system/gd/hci/acl_manager/round_robin_scheduler_test.cc b/system/gd/hci/acl_manager/round_robin_scheduler_test.cc
index 25bd2aff80..b990332c9e 100644
--- a/system/gd/hci/acl_manager/round_robin_scheduler_test.cc
+++ b/system/gd/hci/acl_manager/round_robin_scheduler_test.cc
@@ -16,7 +16,6 @@
#include "hci/acl_manager/round_robin_scheduler.h"
-#include <com_android_bluetooth_flags.h>
#include <gtest/gtest.h>
#include "common/bidi_queue.h"
@@ -422,8 +421,6 @@ TEST_F(RoundRobinSchedulerTest, receive_le_credit_when_next_fragment_is_classic)
}
TEST_F(RoundRobinSchedulerTest, unregister_reclaim_credits) {
- com::android::bluetooth::flags::provider_->drop_acl_fragment_on_disconnect(true);
-
uint16_t handle = 0x01;
auto connection_queue = std::make_shared<AclConnection::Queue>(20);
auto new_connection_queue = std::make_shared<AclConnection::Queue>(20);
diff --git a/system/gd/hci/controller.cc b/system/gd/hci/controller.cc
index b14e434781..919643f14d 100644
--- a/system/gd/hci/controller.cc
+++ b/system/gd/hci/controller.cc
@@ -61,9 +61,7 @@ struct Controller::impl {
handler->BindOn(this, &Controller::impl::NumberOfCompletedPackets));
set_event_mask(kDefaultEventMask);
- if (com::android::bluetooth::flags::encryption_change_v2()) {
- set_event_mask_page_2(kDefaultEventMaskPage2);
- }
+ set_event_mask_page_2(kDefaultEventMaskPage2);
write_le_host_support(Enable::ENABLED, Enable::DISABLED);
hci_->EnqueueCommand(
diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc
index 6bdfde00b9..6e57f2c9d5 100644
--- a/system/gd/hci/distance_measurement_manager.cc
+++ b/system/gd/hci/distance_measurement_manager.cc
@@ -441,6 +441,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
it->second.measurement_ongoing = true;
it->second.waiting_for_start_callback = true;
it->second.local_hci_role = local_hci_role;
+ it->second.retry_counter_for_create_config = 0;
+ it->second.retry_counter_for_cs_enable = 0;
return true;
}
@@ -845,6 +847,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
static void reset_tracker_on_stopped(CsTracker& cs_tracker) {
cs_tracker.measurement_ongoing = false;
cs_tracker.state = CsTrackerState::STOPPED;
+ cs_tracker.procedure_data_list.clear();
}
void handle_cs_setup_failure(uint16_t connection_handle, DistanceMeasurementErrorCode errorCode) {
@@ -906,7 +909,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
if (cs_requester_trackers_.find(connection_handle) != cs_requester_trackers_.end()) {
reset_tracker_on_stopped(cs_requester_trackers_[connection_handle]);
}
- } else if (status_view.GetStatus() != ErrorCode::SUCCESS) {
+ } else if (enable == Enable::ENABLED && status_view.GetStatus() != ErrorCode::SUCCESS) {
if (cs_requester_trackers_.count(connection_handle) == 0) {
log::error("Error code {} for connection_handle {}. No request tracker found.",
ErrorCodeText(status), connection_handle);
@@ -919,6 +922,14 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
if (cs_requester_trackers_[connection_handle].retry_counter_for_cs_enable++ >=
kMaxRetryCounterForCsEnable) {
handle_cs_setup_failure(connection_handle, REASON_INTERNAL_ERROR);
+ } else {
+ cs_requester_trackers_[connection_handle].procedure_schedule_guard_alarm->Cancel();
+ log::info("schedule next procedure enable after {} ms",
+ cs_requester_trackers_[connection_handle].interval_ms);
+ cs_requester_trackers_[connection_handle].procedure_schedule_guard_alarm->Schedule(
+ common::Bind(&impl::send_le_cs_procedure_enable, common::Unretained(this),
+ connection_handle, Enable::ENABLED),
+ std::chrono::milliseconds(cs_requester_trackers_[connection_handle].interval_ms));
}
}
}
@@ -1237,25 +1248,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
void on_cs_procedure_enable_complete(LeCsProcedureEnableCompleteView event_view) {
log::assert_that(event_view.IsValid(), "assert failed: event_view.IsValid()");
uint16_t connection_handle = event_view.GetConnectionHandle();
- log::debug("on cs procedure enabled complete");
- if (event_view.GetStatus() != ErrorCode::SUCCESS) {
- std::string error_code = ErrorCodeText(event_view.GetStatus());
- if (cs_requester_trackers_.count(connection_handle) == 0) {
- log::warn(
- "Received LeCsProcedureEnableCompleteView with error code {}, No request tracker "
- "found",
- error_code);
- handle_cs_setup_failure(connection_handle, REASON_INTERNAL_ERROR);
- return;
- }
- log::warn("Received LeCsProcedureEnableCompleteView with error code {}. Retry counter {}",
- error_code, cs_requester_trackers_[connection_handle].retry_counter_for_cs_enable);
- if (cs_requester_trackers_[connection_handle].retry_counter_for_cs_enable++ >=
- kMaxRetryCounterForCsEnable) {
- handle_cs_setup_failure(connection_handle, REASON_INTERNAL_ERROR);
- }
- return;
- }
+ log::debug("Procedure enabled, {}", event_view.ToString());
+
uint8_t config_id = event_view.GetConfigId();
CsTracker* live_tracker = nullptr;
@@ -1272,7 +1266,7 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
live_tracker = get_live_tracker(connection_handle, config_id, valid_requester_states,
valid_responder_states);
if (live_tracker == nullptr) {
- log::error("no tracker is available for {}", connection_handle);
+ log::error("enable - no tracker is available for {}", connection_handle);
return;
}
if (live_tracker->used_config_id != config_id) {
@@ -1280,7 +1274,22 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
live_tracker->used_config_id);
return;
}
- log::debug("Procedure enabled, {}", event_view.ToString());
+
+ if (live_tracker->local_start && event_view.GetStatus() != ErrorCode::SUCCESS) {
+ log::warn("Received LeCsProcedureEnableCompleteView with error code {}. Retry counter {}",
+ ErrorCodeText(event_view.GetStatus()), live_tracker->retry_counter_for_cs_enable);
+ if (live_tracker->retry_counter_for_cs_enable++ >= kMaxRetryCounterForCsEnable) {
+ handle_cs_setup_failure(connection_handle, REASON_INTERNAL_ERROR);
+ } else {
+ live_tracker->procedure_schedule_guard_alarm->Cancel();
+ log::info("schedule next procedure enable after {} ms", live_tracker->interval_ms);
+ live_tracker->procedure_schedule_guard_alarm->Schedule(
+ common::Bind(&impl::send_le_cs_procedure_enable, common::Unretained(this),
+ connection_handle, Enable::ENABLED),
+ std::chrono::milliseconds(live_tracker->interval_ms));
+ }
+ return;
+ }
live_tracker->state = CsTrackerState::STARTED;
live_tracker->selected_tx_power = event_view.GetSelectedTxPower();
live_tracker->n_procedure_count = event_view.GetProcedureCount();
@@ -1297,38 +1306,45 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback {
if (live_tracker->n_procedure_count >= 1) {
live_tracker->procedure_schedule_guard_alarm->Cancel();
log::info("schedule next procedure enable after {} ms", schedule_interval);
- cs_requester_trackers_[connection_handle].procedure_schedule_guard_alarm->Schedule(
+ live_tracker->procedure_schedule_guard_alarm->Schedule(
common::Bind(&impl::send_le_cs_procedure_enable, common::Unretained(this),
connection_handle, Enable::ENABLED),
std::chrono::milliseconds(schedule_interval));
}
- }
- if (live_tracker->local_start && live_tracker->waiting_for_start_callback) {
- live_tracker->waiting_for_start_callback = false;
- distance_measurement_callbacks_->OnDistanceMeasurementStarted(live_tracker->address,
- METHOD_CS);
- }
- if (live_tracker->local_start && is_hal_v2()) {
- // reset the procedure sequence
- live_tracker->procedure_sequence_after_enable = -1;
- ranging_hal_->UpdateProcedureEnableConfig(connection_handle, event_view);
+ if (live_tracker->waiting_for_start_callback) {
+ live_tracker->waiting_for_start_callback = false;
+ distance_measurement_callbacks_->OnDistanceMeasurementStarted(live_tracker->address,
+ METHOD_CS);
+ }
+ if (is_hal_v2()) {
+ // reset the procedure sequence
+ live_tracker->procedure_sequence_after_enable = -1;
+ ranging_hal_->UpdateProcedureEnableConfig(connection_handle, event_view);
+ }
}
} else if (event_view.GetState() == Enable::DISABLED) {
- uint8_t valid_requester_states = static_cast<uint8_t>(CsTrackerState::STARTED);
- uint8_t valid_responder_states = static_cast<uint8_t>(CsTrackerState::STARTED);
- live_tracker = get_live_tracker(connection_handle, config_id, valid_requester_states,
- valid_responder_states);
- if (live_tracker == nullptr) {
- log::error("no tracker is available for {}", connection_handle);
- return;
+ if (event_view.GetStatus() == ErrorCode::SUCCESS) {
+ // local or remote host requested it.
+ uint8_t valid_requester_states = static_cast<uint8_t>(CsTrackerState::STARTED);
+ uint8_t valid_responder_states = static_cast<uint8_t>(CsTrackerState::STARTED);
+ live_tracker = get_live_tracker(connection_handle, config_id, valid_requester_states,
+ valid_responder_states);
+ if (live_tracker == nullptr) {
+ log::error("disable - no tracker is available for {}", connection_handle);
+ return;
+ }
+ reset_tracker_on_stopped(*live_tracker);
+ } else {
+ // work around, controller may send 'DISABLE' complete with error for 'ENABLE' command
+ auto req_it = cs_requester_trackers_.find(connection_handle);
+ if (req_it != cs_requester_trackers_.end() &&
+ req_it->second.state == CsTrackerState::WAIT_FOR_PROCEDURE_ENABLED &&
+ config_id == req_it->second.used_config_id) {
+ log::warn("expect ENABLE complete, bug got DISABLE complete.");
+ handle_cs_setup_failure(connection_handle, REASON_INTERNAL_ERROR);
+ }
}
- reset_tracker_on_stopped(*live_tracker);
- }
- // reset the procedure data list.
- std::vector<CsProcedureData>& data_list = live_tracker->procedure_data_list;
- while (!data_list.empty()) {
- data_list.erase(data_list.begin());
}
}
diff --git a/system/gd/hci/distance_measurement_manager_test.cc b/system/gd/hci/distance_measurement_manager_test.cc
index 98ab5a4573..35a629c53a 100644
--- a/system/gd/hci/distance_measurement_manager_test.cc
+++ b/system/gd/hci/distance_measurement_manager_test.cc
@@ -21,6 +21,8 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include "common/bind.h"
+#include "common/strings.h"
#include "hal/ranging_hal.h"
#include "hal/ranging_hal_mock.h"
#include "hci/acl_manager_mock.h"
@@ -31,14 +33,20 @@
#include "hci/hci_layer.h"
#include "hci/hci_layer_fake.h"
#include "module.h"
+#include "os/fake_timer/fake_timerfd.h"
#include "packet/packet_view.h"
#include "ras/ras_packets.h"
+using bluetooth::os::fake_timer::fake_timerfd_advance;
+using bluetooth::os::fake_timer::fake_timerfd_reset;
+using testing::_;
using testing::AtLeast;
using testing::Return;
namespace {
-constexpr auto kTimeout = std::chrono::seconds(1);
+static constexpr auto kTimeout = std::chrono::seconds(1);
+static constexpr uint8_t kMaxRetryCounterForCreateConfig = 0x03;
+static constexpr uint8_t kMaxRetryCounterForCsEnable = 0x03;
}
namespace bluetooth {
@@ -52,6 +60,9 @@ protected:
};
class TestAclManager : public testing::MockAclManager {
+public:
+ void AddDeviceToRelaxedConnectionIntervalList(const Address /*address*/) override {}
+
protected:
void Start() override {}
void Stop() override {}
@@ -65,7 +76,7 @@ struct CsReadCapabilitiesCompleteEvent {
uint8_t num_antennas_supported = 2;
uint8_t max_antenna_paths_supported = 4;
CsRoleSupported roles_supported = {/*initiator=*/1, /*reflector=*/1};
- CsOptionalModesSupported modes_supported = {/*mode_3=*/1};
+ unsigned char modes_supported = {/*mode_3=*/1};
CsRttCapability rtt_capability = {/*rtt_aa_only_n=*/1, /*rtt_sounding_n=*/1,
/*rtt_random_payload_n=*/1};
uint8_t rtt_aa_only_n = 1;
@@ -74,7 +85,7 @@ struct CsReadCapabilitiesCompleteEvent {
CsOptionalNadmSoundingCapability nadm_sounding_capability = {
/*normalized_attack_detector_metric=*/1};
CsOptionalNadmRandomCapability nadm_random_capability = {/*normalized_attack_detector_metric=*/1};
- CsOptionalCsSyncPhysSupported cs_sync_phys_supported = {/*le_2m_phy=*/1};
+ CsOptionalCsSyncPhysSupported cs_sync_phys_supported = {/*le_2m_phy=*/1, /*le_2m_2bt_phy=*/0};
CsOptionalSubfeaturesSupported subfeatures_supported = {/*no_frequency_actuation_error=*/1,
/*channel_selection_algorithm=*/1,
/*phase_based_ranging=*/1};
@@ -101,6 +112,53 @@ struct CsReadCapabilitiesCompleteEvent {
uint8_t tx_snr_capability = 1;
};
+struct CsConfigCompleteEvent {
+ ErrorCode status = ErrorCode::SUCCESS;
+ uint8_t config_id = 0;
+ CsAction action = CsAction::CONFIG_CREATED;
+ CsMainModeType main_mode_type = CsMainModeType::MODE_2;
+ CsSubModeType sub_mode_type = CsSubModeType::UNUSED;
+ uint8_t min_main_mode_steps = 3; // 0x02 to 0xFF
+ uint8_t max_main_mode_steps = 100; // 0x02 to 0xFF
+ uint8_t main_mode_repetition = 0; // 0x00 to 0x03
+ uint8_t mode_0_steps = 1; // 0x01 to 0x03
+ CsRole cs_role = CsRole::INITIATOR;
+ CsRttType rtt_type = CsRttType::RTT_AA_ONLY;
+ CsSyncPhy sync_phy = CsSyncPhy::LE_2M_PHY;
+ std::array<uint8_t, 10> channel_map = GetChannelMap("1FFFFFFFFFFFFC7FFFFC");
+ uint8_t channel_map_repetition = 1; // 0x01 to 0xFF
+ CsChannelSelectionType channel_selection_type = CsChannelSelectionType::TYPE_3C;
+ CsCh3cShape ch3c_shape = CsCh3cShape::HAT_SHAPE;
+ uint8_t ch3c_jump = 2; // 0x02 to 0x08
+ uint8_t t_ip1_time = 0x0A; // 0x0A, 0x14, 0x1E, 0x28, 0x32, 0x3C, 0x50, or 0x91
+ uint8_t t_ip2_time = 0x0A; // 0x0A, 0x14, 0x1E, 0x28, 0x32, 0x3C, 0x50, or 0x91
+ uint8_t t_fcs_time = 0x0F; // 0x0F, 0x14, 0x1E, 0x28, 0x32, 0x3C, 0x50, 0x64, 0x78, or 0x96
+ uint8_t t_pm_time = 0x0A; // 0x0A, 0x14, or 0x28
+
+ static const std::array<uint8_t, 10> GetChannelMap(const std::string& hex_string) {
+ assert(hex_stinrg.length() == 20);
+ auto channel_vector = common::FromHexString(hex_string);
+ std::array<uint8_t, 10> channel_map{};
+ std::copy(channel_vector->begin(), channel_vector->end(), channel_map.begin());
+ std::reverse(channel_map.begin(), channel_map.end());
+ return channel_map;
+ }
+};
+
+struct CsProcedureEnableCompleteEvent {
+ ErrorCode status = ErrorCode::SUCCESS;
+ uint8_t config_id = 0;
+ uint8_t tone_antenna_config_selection = 0;
+ uint8_t selected_tx_power = 0; // -127 to 20 dBm
+ uint32_t subevent_len = 2500; // 1250us to 4s
+ uint8_t subevents_per_event = 1; // 0x01 to 0x20
+ uint16_t subevent_interval = 1; // N x 0.625ms
+ uint16_t event_interval = 0; // number of acl conn interval
+ uint16_t procedure_interval = 2; // number of acl conn interval
+ uint16_t procedure_count = 5; // 0x0001 to 0xFFFF
+ uint16_t max_procedure_len = 10; // N x 0.625 ms
+};
+
struct StartMeasurementParameters {
Address remote_address = Address::FromString("12:34:56:78:9a:bc").value();
uint16_t connection_handle = 64;
@@ -126,6 +184,7 @@ protected:
EXPECT_CALL(*mock_controller_, SupportsBleChannelSounding()).WillOnce(Return(true));
EXPECT_CALL(*mock_ranging_hal_, IsBound()).Times(AtLeast(1)).WillRepeatedly(Return(true));
+ EXPECT_CALL(*mock_ranging_hal_, GetRangingHalVersion).WillRepeatedly(Return(hal::V_2));
handler_ = fake_registry_.GetTestHandler();
dm_manager_ = fake_registry_.Start<DistanceMeasurementManager>(&thread_, handler_);
@@ -145,6 +204,19 @@ protected:
return dm_session_promise_->get_future();
}
+ std::future<void> fake_timer_advance(uint64_t ms) {
+ std::promise<void> promise;
+ auto future = promise.get_future();
+ handler_->Post(common::BindOnce(
+ [](std::promise<void> promise, uint64_t ms) {
+ fake_timerfd_advance(ms);
+ promise.set_value();
+ },
+ common::Passed(std::move(promise)), ms));
+
+ return future;
+ }
+
void sync_client_handler() {
log::assert_that(thread_.GetReactor()->WaitForIdle(kTimeout),
"assert failed: thread_.GetReactor()->WaitForIdle(kTimeout)");
@@ -172,6 +244,55 @@ protected:
cs_cap_complete_event.t_sw_time_supported, cs_cap_complete_event.tx_snr_capability);
}
+ static std::unique_ptr<LeCsReadRemoteSupportedCapabilitiesCompleteBuilder>
+ GetRemoteSupportedCapabilitiesCompleteEvent(
+ uint16_t connection_handle,
+ const CsReadCapabilitiesCompleteEvent& cs_cap_complete_event) {
+ return LeCsReadRemoteSupportedCapabilitiesCompleteBuilder::Create(
+ cs_cap_complete_event.error_code, connection_handle,
+ cs_cap_complete_event.num_config_supported,
+ cs_cap_complete_event.max_consecutive_procedures_supported,
+ cs_cap_complete_event.num_antennas_supported,
+ cs_cap_complete_event.max_antenna_paths_supported,
+ cs_cap_complete_event.roles_supported, cs_cap_complete_event.modes_supported,
+ cs_cap_complete_event.rtt_capability, cs_cap_complete_event.rtt_aa_only_n,
+ cs_cap_complete_event.rtt_sounding_n, cs_cap_complete_event.rtt_random_payload_n,
+ cs_cap_complete_event.nadm_sounding_capability,
+ cs_cap_complete_event.nadm_random_capability,
+ cs_cap_complete_event.cs_sync_phys_supported,
+ cs_cap_complete_event.subfeatures_supported,
+ cs_cap_complete_event.t_ip1_times_supported,
+ cs_cap_complete_event.t_ip2_times_supported,
+ cs_cap_complete_event.t_fcs_times_supported, cs_cap_complete_event.t_pm_times_supported,
+ cs_cap_complete_event.t_sw_time_supported, cs_cap_complete_event.tx_snr_capability);
+ }
+
+ static std::unique_ptr<LeCsConfigCompleteBuilder> GetConfigCompleteEvent(
+ uint16_t connection_handle, CsConfigCompleteEvent complete_event) {
+ return LeCsConfigCompleteBuilder::Create(
+ complete_event.status, connection_handle, complete_event.config_id,
+ complete_event.action, complete_event.main_mode_type, complete_event.sub_mode_type,
+ complete_event.min_main_mode_steps, complete_event.max_main_mode_steps,
+ complete_event.main_mode_repetition, complete_event.mode_0_steps,
+ complete_event.cs_role, complete_event.rtt_type, complete_event.sync_phy,
+ complete_event.channel_map, complete_event.channel_map_repetition,
+ complete_event.channel_selection_type, complete_event.ch3c_shape,
+ complete_event.ch3c_jump, complete_event.t_ip1_time, complete_event.t_ip2_time,
+ complete_event.t_fcs_time, complete_event.t_pm_time);
+ }
+
+ static std::unique_ptr<LeCsProcedureEnableCompleteBuilder> GetProcedureEnableCompleteEvent(
+ uint16_t connection_handle, Enable enable,
+ CsProcedureEnableCompleteEvent complete_event) {
+ return LeCsProcedureEnableCompleteBuilder::Create(
+ complete_event.status, connection_handle, complete_event.config_id, enable,
+ complete_event.tone_antenna_config_selection, complete_event.selected_tx_power,
+ complete_event.subevent_len, complete_event.subevents_per_event,
+ complete_event.subevent_interval, complete_event.event_interval,
+ complete_event.procedure_interval, complete_event.procedure_count,
+ complete_event.max_procedure_len);
+ }
+
void StartMeasurement(const StartMeasurementParameters& params) {
dm_manager_->StartDistanceMeasurement(params.remote_address, params.connection_handle,
params.local_hci_role, params.interval, params.method);
@@ -183,6 +304,72 @@ protected:
GetLocalSupportedCapabilitiesCompleteEvent(read_cs_complete_event));
}
+ void StartMeasurementTillRasConnectedEvent(const StartMeasurementParameters& params) {
+ ReceivedReadLocalCapabilitiesComplete();
+ EXPECT_CALL(*mock_ranging_hal_, OpenSession(_, _, _))
+ .WillOnce([this](uint16_t connection_handle, uint16_t /*att_handle*/,
+ const std::vector<hal::VendorSpecificCharacteristic>&
+ vendor_specific_data) {
+ mock_ranging_hal_->GetRangingHalCallback()->OnOpened(connection_handle,
+ vendor_specific_data);
+ });
+ StartMeasurement(params);
+ dm_manager_->HandleRasClientConnectedEvent(
+ params.remote_address, params.connection_handle,
+ /*att_handle=*/0,
+ /*vendor_specific_data=*/std::vector<hal::VendorSpecificCharacteristic>(),
+ /*conn_interval=*/24);
+ }
+
+ void StartMeasurementTillReadRemoteCaps(const StartMeasurementParameters& params) {
+ StartMeasurementTillRasConnectedEvent(params);
+
+ test_hci_layer_->GetCommand(OpCode::LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES);
+ CsReadCapabilitiesCompleteEvent read_cs_complete_event;
+ test_hci_layer_->IncomingEvent(LeCsReadRemoteSupportedCapabilitiesStatusBuilder::Create(
+ /*status=*/ErrorCode::SUCCESS,
+ /*num_hci_command_packets=*/0xFF));
+ test_hci_layer_->IncomingLeMetaEvent(GetRemoteSupportedCapabilitiesCompleteEvent(
+ params.connection_handle, read_cs_complete_event));
+
+ test_hci_layer_->GetCommand(OpCode::LE_CS_SET_DEFAULT_SETTINGS);
+ test_hci_layer_->IncomingEvent(LeCsSetDefaultSettingsCompleteBuilder::Create(
+ /*num_hci_command_packets=*/static_cast<uint8_t>(0xEE), ErrorCode::SUCCESS,
+ params.connection_handle));
+ }
+
+ void StartMeasurementTillCreateConfig(const StartMeasurementParameters& params) {
+ StartMeasurementTillReadRemoteCaps(params);
+
+ CsConfigCompleteEvent cs_config_complete_event;
+ test_hci_layer_->GetCommand(OpCode::LE_CS_CREATE_CONFIG);
+ test_hci_layer_->IncomingEvent(LeCsCreateConfigStatusBuilder::Create(
+ /*status=*/ErrorCode::SUCCESS,
+ /*num_hci_command_packets=*/0xFF));
+ test_hci_layer_->IncomingLeMetaEvent(
+ GetConfigCompleteEvent(params.connection_handle, cs_config_complete_event));
+ }
+
+ void StartMeasurementTillSecurityEnable(const StartMeasurementParameters& params) {
+ StartMeasurementTillCreateConfig(params);
+
+ test_hci_layer_->GetCommand(OpCode::LE_CS_SECURITY_ENABLE);
+ test_hci_layer_->IncomingEvent(LeCsSecurityEnableStatusBuilder::Create(
+ /*status=*/ErrorCode::SUCCESS,
+ /*num_hci_command_packets=*/0xFF));
+ test_hci_layer_->IncomingLeMetaEvent(LeCsSecurityEnableCompleteBuilder::Create(
+ ErrorCode::SUCCESS, params.connection_handle));
+ }
+
+ void StartMeasurementTillSetProcedureParameters(const StartMeasurementParameters& params) {
+ StartMeasurementTillSecurityEnable(params);
+
+ test_hci_layer_->GetCommand(OpCode::LE_CS_SET_PROCEDURE_PARAMETERS);
+ test_hci_layer_->IncomingEvent(LeCsSetProcedureParametersCompleteBuilder::Create(
+ /*num_hci_command_packets=*/static_cast<uint8_t>(0xEE), ErrorCode::SUCCESS,
+ params.connection_handle));
+ }
+
protected:
TestModuleRegistry fake_registry_;
HciLayerFake* test_hci_layer_ = nullptr;
@@ -250,6 +437,193 @@ TEST_F(DistanceMeasurementManagerTest, ras_remote_not_support) {
dm_session_future.wait_for(kTimeout);
sync_client_handler();
}
+
+TEST_F(DistanceMeasurementManagerTest, error_read_remote_cs_caps_command) {
+ auto dm_session_future = GetDmSessionFuture();
+ StartMeasurementParameters params;
+ StartMeasurementTillRasConnectedEvent(params);
+
+ EXPECT_CALL(mock_dm_callbacks_,
+ OnDistanceMeasurementStopped(params.remote_address,
+ DistanceMeasurementErrorCode::REASON_INTERNAL_ERROR,
+ DistanceMeasurementMethod::METHOD_CS))
+ .WillOnce([this](const Address& /*address*/, DistanceMeasurementErrorCode /*error_code*/,
+ DistanceMeasurementMethod /*method*/) {
+ ASSERT_NE(dm_session_promise_, nullptr);
+ dm_session_promise_->set_value();
+ dm_session_promise_.reset();
+ });
+
+ test_hci_layer_->GetCommand(OpCode::LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES);
+ test_hci_layer_->IncomingEvent(LeCsReadRemoteSupportedCapabilitiesStatusBuilder::Create(
+ /*status=*/ErrorCode::COMMAND_DISALLOWED,
+ /*num_hci_command_packets=*/0xff));
+ sync_client_handler();
+}
+
+TEST_F(DistanceMeasurementManagerTest, fail_read_remote_cs_caps_complete) {
+ auto dm_session_future = GetDmSessionFuture();
+ StartMeasurementParameters params;
+ StartMeasurementTillRasConnectedEvent(params);
+
+ EXPECT_CALL(mock_dm_callbacks_,
+ OnDistanceMeasurementStopped(params.remote_address,
+ DistanceMeasurementErrorCode::REASON_INTERNAL_ERROR,
+ DistanceMeasurementMethod::METHOD_CS))
+ .WillOnce([this](const Address& /*address*/, DistanceMeasurementErrorCode /*error_code*/,
+ DistanceMeasurementMethod /*method*/) {
+ ASSERT_NE(dm_session_promise_, nullptr);
+ dm_session_promise_->set_value();
+ dm_session_promise_.reset();
+ });
+
+ test_hci_layer_->GetCommand(OpCode::LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES);
+ CsReadCapabilitiesCompleteEvent read_cs_complete_event;
+ read_cs_complete_event.error_code = ErrorCode::COMMAND_DISALLOWED;
+ test_hci_layer_->IncomingLeMetaEvent(GetRemoteSupportedCapabilitiesCompleteEvent(
+ params.connection_handle, read_cs_complete_event));
+ sync_client_handler();
+}
+
+TEST_F(DistanceMeasurementManagerTest, error_create_config_command) {
+ auto dm_session_future = GetDmSessionFuture();
+ StartMeasurementParameters params;
+ StartMeasurementTillReadRemoteCaps(params);
+
+ EXPECT_CALL(mock_dm_callbacks_,
+ OnDistanceMeasurementStopped(params.remote_address,
+ DistanceMeasurementErrorCode::REASON_INTERNAL_ERROR,
+ DistanceMeasurementMethod::METHOD_CS))
+ .WillOnce([this](const Address& /*address*/, DistanceMeasurementErrorCode /*error_code*/,
+ DistanceMeasurementMethod /*method*/) {
+ ASSERT_NE(dm_session_promise_, nullptr);
+ dm_session_promise_->set_value();
+ dm_session_promise_.reset();
+ });
+
+ test_hci_layer_->GetCommand(OpCode::LE_CS_CREATE_CONFIG);
+ test_hci_layer_->IncomingEvent(LeCsCreateConfigStatusBuilder::Create(
+ /*status=*/ErrorCode::COMMAND_DISALLOWED,
+ /*num_hci_command_packets=*/0xff));
+ sync_client_handler();
+}
+
+TEST_F(DistanceMeasurementManagerTest, fail_create_config_complete) {
+ auto dm_session_future = GetDmSessionFuture();
+ StartMeasurementParameters params;
+ StartMeasurementTillReadRemoteCaps(params);
+
+ EXPECT_CALL(mock_dm_callbacks_,
+ OnDistanceMeasurementStopped(params.remote_address,
+ DistanceMeasurementErrorCode::REASON_INTERNAL_ERROR,
+ DistanceMeasurementMethod::METHOD_CS))
+ .WillOnce([this](const Address& /*address*/, DistanceMeasurementErrorCode /*error_code*/,
+ DistanceMeasurementMethod /*method*/) {
+ ASSERT_NE(dm_session_promise_, nullptr);
+ dm_session_promise_->set_value();
+ dm_session_promise_.reset();
+ });
+
+ CsConfigCompleteEvent cs_config_complete_event;
+ cs_config_complete_event.status = ErrorCode::COMMAND_DISALLOWED;
+ for (int i = 0; i <= kMaxRetryCounterForCreateConfig; i++) {
+ test_hci_layer_->GetCommand(OpCode::LE_CS_CREATE_CONFIG);
+ test_hci_layer_->IncomingLeMetaEvent(
+ GetConfigCompleteEvent(params.connection_handle, cs_config_complete_event));
+ }
+ sync_client_handler();
+}
+
+TEST_F(DistanceMeasurementManagerTest, retry_fail_procedure_enable_command) {
+ auto dm_session_future = GetDmSessionFuture();
+ StartMeasurementParameters params;
+ StartMeasurementTillSetProcedureParameters(params);
+
+ EXPECT_CALL(mock_dm_callbacks_,
+ OnDistanceMeasurementStopped(params.remote_address,
+ DistanceMeasurementErrorCode::REASON_INTERNAL_ERROR,
+ DistanceMeasurementMethod::METHOD_CS))
+ .WillOnce([this](const Address& /*address*/, DistanceMeasurementErrorCode /*error_code*/,
+ DistanceMeasurementMethod /*method*/) {
+ ASSERT_NE(dm_session_promise_, nullptr);
+ dm_session_promise_->set_value();
+ dm_session_promise_.reset();
+ });
+
+ for (int i = 0; i <= kMaxRetryCounterForCsEnable; i++) {
+ test_hci_layer_->GetCommand(OpCode::LE_CS_PROCEDURE_ENABLE);
+ test_hci_layer_->IncomingEvent(LeCsProcedureEnableStatusBuilder::Create(
+ /*status=*/ErrorCode::COMMAND_DISALLOWED,
+ /*num_hci_command_packets=*/0xff));
+ auto future = fake_timer_advance(params.interval + 10);
+ future.wait_for(kTimeout);
+ sync_client_handler();
+ }
+ fake_timerfd_reset();
+ sync_client_handler();
+}
+
+TEST_F(DistanceMeasurementManagerTest, retry_fail_procedure_enable_complete) {
+ auto dm_session_future = GetDmSessionFuture();
+ StartMeasurementParameters params;
+ StartMeasurementTillSetProcedureParameters(params);
+
+ EXPECT_CALL(mock_dm_callbacks_,
+ OnDistanceMeasurementStopped(params.remote_address,
+ DistanceMeasurementErrorCode::REASON_INTERNAL_ERROR,
+ DistanceMeasurementMethod::METHOD_CS))
+ .WillOnce([this](const Address& /*address*/, DistanceMeasurementErrorCode /*error_code*/,
+ DistanceMeasurementMethod /*method*/) {
+ ASSERT_NE(dm_session_promise_, nullptr);
+ dm_session_promise_->set_value();
+ dm_session_promise_.reset();
+ });
+
+ CsProcedureEnableCompleteEvent complete_event;
+ complete_event.status = ErrorCode::LINK_LAYER_COLLISION;
+ for (int i = 0; i <= kMaxRetryCounterForCsEnable; i++) {
+ test_hci_layer_->GetCommand(OpCode::LE_CS_PROCEDURE_ENABLE);
+ test_hci_layer_->IncomingEvent(LeCsProcedureEnableStatusBuilder::Create(
+ /*status=*/ErrorCode::SUCCESS,
+ /*num_hci_command_packets=*/0xff));
+ test_hci_layer_->IncomingLeMetaEvent(GetProcedureEnableCompleteEvent(
+ params.connection_handle, Enable::ENABLED, complete_event));
+ auto future = fake_timer_advance(params.interval + 10);
+ future.wait_for(kTimeout);
+ sync_client_handler();
+ }
+ fake_timerfd_reset();
+ sync_client_handler();
+}
+
+TEST_F(DistanceMeasurementManagerTest, unexpected_procedure_enable_complete_as_disable) {
+ auto dm_session_future = GetDmSessionFuture();
+ StartMeasurementParameters params;
+ StartMeasurementTillSetProcedureParameters(params);
+
+ EXPECT_CALL(mock_dm_callbacks_,
+ OnDistanceMeasurementStopped(params.remote_address,
+ DistanceMeasurementErrorCode::REASON_INTERNAL_ERROR,
+ DistanceMeasurementMethod::METHOD_CS))
+ .WillOnce([this](const Address& /*address*/, DistanceMeasurementErrorCode /*error_code*/,
+ DistanceMeasurementMethod /*method*/) {
+ ASSERT_NE(dm_session_promise_, nullptr);
+ dm_session_promise_->set_value();
+ dm_session_promise_.reset();
+ });
+
+ test_hci_layer_->GetCommand(OpCode::LE_CS_PROCEDURE_ENABLE);
+ test_hci_layer_->IncomingEvent(LeCsProcedureEnableStatusBuilder::Create(
+ /*status=*/ErrorCode::SUCCESS,
+ /*num_hci_command_packets=*/0xff));
+ CsProcedureEnableCompleteEvent complete_event;
+ complete_event.status = ErrorCode::LINK_LAYER_COLLISION;
+ test_hci_layer_->IncomingLeMetaEvent(GetProcedureEnableCompleteEvent(
+ params.connection_handle, Enable::DISABLED, complete_event));
+
+ sync_client_handler();
+}
+
} // namespace
} // namespace hci
} // namespace bluetooth
diff --git a/system/gd/hci/hci_layer.cc b/system/gd/hci/hci_layer.cc
index 85d8af092e..da370a7564 100644
--- a/system/gd/hci/hci_layer.cc
+++ b/system/gd/hci/hci_layer.cc
@@ -64,6 +64,11 @@ using std::unique_ptr;
static std::recursive_mutex life_cycle_guard;
static bool life_cycle_stopped = true;
+#ifdef TARGET_FLOSS
+// Signal to indicate the controller needs to be reset.
+const int SIG_RESET_CTRL = SIGUSR1;
+#endif
+
static std::chrono::milliseconds getHciTimeoutMs() {
static auto sHciTimeoutMs = std::chrono::milliseconds(bluetooth::os::GetSystemPropertyUint32Base(
"bluetooth.hci.timeout_milliseconds", HciLayer::kHciTimeoutMs.count()));
@@ -296,12 +301,18 @@ struct HciLayer::impl {
void on_hci_timeout(OpCode op_code) {
#ifdef TARGET_FLOSS
+ std::unique_lock<std::recursive_mutex> lock(life_cycle_guard);
+ if (life_cycle_stopped) {
+ return;
+ }
+
log::warn("Ignoring the timeouted HCI command {}.", OpCodeText(op_code));
- // Terminate the process to trigger controller reset, also mark the controller
- // is broken to prevent further error while terminating.
- auto hal = module_.GetDependency<hal::HciHal>();
- hal->markControllerBroken();
- kill(getpid(), SIGTERM);
+
+ // Terminate the process to trigger controller reset, also stop sending and
+ // processing any incoming packet immediately to prevent further error
+ // while terminating.
+ module_.LifeCycleStop();
+ kill(getpid(), SIG_RESET_CTRL);
return;
#endif
@@ -507,12 +518,11 @@ struct HciLayer::impl {
log::assert_that(event_view.IsValid(), "assert failed: event_view.IsValid()");
#ifdef TARGET_FLOSS
log::warn("Hardware Error Event with code 0x{:02x}", event_view.GetHardwareCode());
- // Sending SIGTERM to process the exception from BT controller.
+ // Sending signal to indicate BT controller needs to reset.
// The Floss daemon will be restarted. HCI reset during restart will clear the
// error state of the BT controller.
- auto hal = module_.GetDependency<hal::HciHal>();
- hal->markControllerBroken();
- kill(getpid(), SIGTERM);
+ module_.LifeCycleStop();
+ kill(getpid(), SIG_RESET_CTRL);
#else
log::fatal("Hardware Error Event with code 0x{:02x}", event_view.GetHardwareCode());
#endif
@@ -619,6 +629,14 @@ struct HciLayer::hal_callbacks : public hal::HciHalCallbacks {
module_.impl_->incoming_iso_buffer_.Enqueue(std::move(iso), module_.GetHandler());
}
+#ifdef TARGET_FLOSS
+ void controllerNeedsReset() override {
+ log::info("Controller needs reset!");
+ module_.LifeCycleStop();
+ kill(getpid(), SIG_RESET_CTRL);
+ }
+#endif
+
HciLayer& module_;
};
@@ -958,6 +976,7 @@ void HciLayer::StartWithNoHalDependencies(Handler* handler) {
void HciLayer::Stop() {
std::unique_lock<std::recursive_mutex> lock(life_cycle_guard);
+ life_cycle_stopped = true;
auto hal = GetDependency<hal::HciHal>();
hal->unregisterIncomingPacketCallback();
delete hal_callbacks_;
@@ -966,7 +985,11 @@ void HciLayer::Stop() {
impl_->sco_queue_.GetDownEnd()->UnregisterDequeue();
impl_->iso_queue_.GetDownEnd()->UnregisterDequeue();
delete impl_;
+}
+// Function to stop sending and handling incoming packets
+void HciLayer::LifeCycleStop() {
+ std::unique_lock<std::recursive_mutex> lock(life_cycle_guard);
life_cycle_stopped = true;
}
diff --git a/system/gd/hci/hci_layer.h b/system/gd/hci/hci_layer.h
index 7f894b2de6..94f706cf6b 100644
--- a/system/gd/hci/hci_layer.h
+++ b/system/gd/hci/hci_layer.h
@@ -149,6 +149,8 @@ protected:
void Stop() override;
+ void LifeCycleStop();
+
virtual void Disconnect(uint16_t handle, ErrorCode reason);
virtual void ReadRemoteVersion(hci::ErrorCode hci_status, uint16_t handle, uint8_t version,
uint16_t manufacturer_name, uint16_t sub_version);
diff --git a/system/gd/hci/le_address_manager.cc b/system/gd/hci/le_address_manager.cc
index 804f88985e..327ea0f0ca 100644
--- a/system/gd/hci/le_address_manager.cc
+++ b/system/gd/hci/le_address_manager.cc
@@ -165,12 +165,8 @@ void LeAddressManager::SetPrivacyPolicyForInitiatorAddress(
min_seconds.count(), max_seconds.count());
enqueue_command_.Run(std::move(packet));
} else {
- if (com::android::bluetooth::flags::non_wake_alarm_for_rpa_rotation()) {
- address_rotation_wake_alarm_ = std::make_unique<os::Alarm>(handler_, true);
- address_rotation_non_wake_alarm_ = std::make_unique<os::Alarm>(handler_, false);
- } else {
- address_rotation_wake_alarm_ = std::make_unique<os::Alarm>(handler_);
- }
+ address_rotation_wake_alarm_ = std::make_unique<os::Alarm>(handler_, true);
+ address_rotation_non_wake_alarm_ = std::make_unique<os::Alarm>(handler_, false);
}
set_random_address();
break;
@@ -229,12 +225,8 @@ void LeAddressManager::SetPrivacyPolicyForInitiatorAddressForTest(
min_seconds.count(), max_seconds.count());
enqueue_command_.Run(std::move(packet));
} else {
- if (com::android::bluetooth::flags::non_wake_alarm_for_rpa_rotation()) {
- address_rotation_wake_alarm_ = std::make_unique<os::Alarm>(handler_, true);
- address_rotation_non_wake_alarm_ = std::make_unique<os::Alarm>(handler_, false);
- } else {
- address_rotation_wake_alarm_ = std::make_unique<os::Alarm>(handler_);
- }
+ address_rotation_wake_alarm_ = std::make_unique<os::Alarm>(handler_, true);
+ address_rotation_non_wake_alarm_ = std::make_unique<os::Alarm>(handler_, false);
set_random_address();
}
break;
@@ -422,31 +414,25 @@ void LeAddressManager::prepare_to_rotate() {
}
void LeAddressManager::schedule_rotate_random_address() {
- if (com::android::bluetooth::flags::non_wake_alarm_for_rpa_rotation()) {
- std::string client_name = "LeAddressManager";
- auto privateAddressIntervalRange = GetNextPrivateAddressIntervalRange(client_name);
- address_rotation_wake_alarm_->Schedule(
- common::BindOnce(
- []() { log::info("deadline wakeup in schedule_rotate_random_address"); }),
- privateAddressIntervalRange.max);
- address_rotation_non_wake_alarm_->Schedule(
- common::BindOnce(&LeAddressManager::prepare_to_rotate, common::Unretained(this)),
- privateAddressIntervalRange.min);
-
- auto now = std::chrono::system_clock::now();
- if (address_rotation_interval_min.has_value()) {
- CheckAddressRotationHappenedInExpectedTimeInterval(
- *address_rotation_interval_min, *address_rotation_interval_max, now, client_name);
- }
-
- // Update the expected range here.
- address_rotation_interval_min.emplace(now + privateAddressIntervalRange.min);
- address_rotation_interval_max.emplace(now + privateAddressIntervalRange.max);
- } else {
- address_rotation_wake_alarm_->Schedule(
- common::BindOnce(&LeAddressManager::prepare_to_rotate, common::Unretained(this)),
- GetNextPrivateAddressIntervalMs());
+ std::string client_name = "LeAddressManager";
+ auto privateAddressIntervalRange = GetNextPrivateAddressIntervalRange(client_name);
+ address_rotation_wake_alarm_->Schedule(
+ common::BindOnce(
+ []() { log::info("deadline wakeup in schedule_rotate_random_address"); }),
+ privateAddressIntervalRange.max);
+ address_rotation_non_wake_alarm_->Schedule(
+ common::BindOnce(&LeAddressManager::prepare_to_rotate, common::Unretained(this)),
+ privateAddressIntervalRange.min);
+
+ auto now = std::chrono::system_clock::now();
+ if (address_rotation_interval_min.has_value()) {
+ CheckAddressRotationHappenedInExpectedTimeInterval(
+ *address_rotation_interval_min, *address_rotation_interval_max, now, client_name);
}
+
+ // Update the expected range here.
+ address_rotation_interval_min.emplace(now + privateAddressIntervalRange.min);
+ address_rotation_interval_max.emplace(now + privateAddressIntervalRange.max);
}
void LeAddressManager::set_random_address() {
diff --git a/system/gd/hci/le_advertising_manager.cc b/system/gd/hci/le_advertising_manager.cc
index f9a80f44f8..d626b2ee15 100644
--- a/system/gd/hci/le_advertising_manager.cc
+++ b/system/gd/hci/le_advertising_manager.cc
@@ -374,39 +374,29 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
log::info("Reenable advertising");
if (was_rotating_address) {
log::info("Scheduling address rotation for advertiser_id={}", advertiser_id);
- if (com::android::bluetooth::flags::non_wake_alarm_for_rpa_rotation()) {
- advertising_sets_[advertiser_id].address_rotation_wake_alarm_ =
- std::make_unique<os::Alarm>(module_handler_, true);
- advertising_sets_[advertiser_id].address_rotation_non_wake_alarm_ =
- std::make_unique<os::Alarm>(module_handler_, false);
-
- std::string client_name = "advertising_set_" + std::to_string(advertiser_id);
- auto privateAddressIntervalRange =
- le_address_manager_->GetNextPrivateAddressIntervalRange(client_name);
-
- advertising_sets_[advertiser_id].address_rotation_wake_alarm_->Schedule(
- common::BindOnce(
- []() { log::info("deadline wakeup in handle_set_terminated"); }),
- privateAddressIntervalRange.max);
- advertising_sets_[advertiser_id].address_rotation_non_wake_alarm_->Schedule(
- common::BindOnce(&impl::set_advertising_set_random_address_on_timer,
- common::Unretained(this), advertiser_id),
- privateAddressIntervalRange.min);
-
- // Update the expected range here.
- auto now = std::chrono::system_clock::now();
- advertising_sets_[advertiser_id].address_rotation_interval_min.emplace(
- now + privateAddressIntervalRange.min);
- advertising_sets_[advertiser_id].address_rotation_interval_max.emplace(
- now + privateAddressIntervalRange.max);
- } else {
- advertising_sets_[advertiser_id].address_rotation_wake_alarm_ =
- std::make_unique<os::Alarm>(module_handler_);
- advertising_sets_[advertiser_id].address_rotation_wake_alarm_->Schedule(
- common::BindOnce(&impl::set_advertising_set_random_address_on_timer,
- common::Unretained(this), advertiser_id),
- le_address_manager_->GetNextPrivateAddressIntervalMs());
- }
+ advertising_sets_[advertiser_id].address_rotation_wake_alarm_ =
+ std::make_unique<os::Alarm>(module_handler_, true);
+ advertising_sets_[advertiser_id].address_rotation_non_wake_alarm_ =
+ std::make_unique<os::Alarm>(module_handler_, false);
+
+ std::string client_name = "advertising_set_" + std::to_string(advertiser_id);
+ auto privateAddressIntervalRange =
+ le_address_manager_->GetNextPrivateAddressIntervalRange(client_name);
+
+ advertising_sets_[advertiser_id].address_rotation_wake_alarm_->Schedule(
+ common::BindOnce([]() { log::info("deadline wakeup in handle_set_terminated"); }),
+ privateAddressIntervalRange.max);
+ advertising_sets_[advertiser_id].address_rotation_non_wake_alarm_->Schedule(
+ common::BindOnce(&impl::set_advertising_set_random_address_on_timer,
+ common::Unretained(this), advertiser_id),
+ privateAddressIntervalRange.min);
+
+ // Update the expected range here.
+ auto now = std::chrono::system_clock::now();
+ advertising_sets_[advertiser_id].address_rotation_interval_min.emplace(
+ now + privateAddressIntervalRange.min);
+ advertising_sets_[advertiser_id].address_rotation_interval_max.emplace(
+ now + privateAddressIntervalRange.max);
}
enable_advertiser(advertiser_id, true, 0, 0);
}
@@ -673,40 +663,31 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
!leaudio_requested_nrpa && (!controller_->IsRpaGenerationSupported())) {
// start timer for random address
log::info("Scheduling address rotation for advertiser_id={}", id);
- if (com::android::bluetooth::flags::non_wake_alarm_for_rpa_rotation()) {
- advertising_sets_[id].address_rotation_wake_alarm_ =
- std::make_unique<os::Alarm>(module_handler_, true);
- advertising_sets_[id].address_rotation_non_wake_alarm_ =
- std::make_unique<os::Alarm>(module_handler_, false);
-
- std::string client_name = "advertising_set_" + std::to_string(id);
- auto privateAddressIntervalRange =
- le_address_manager_->GetNextPrivateAddressIntervalRange(client_name);
-
- advertising_sets_[id].address_rotation_wake_alarm_->Schedule(
- common::BindOnce([]() {
- log::info("deadline wakeup in create_extended_advertiser_with_id");
- }),
- privateAddressIntervalRange.max);
- advertising_sets_[id].address_rotation_non_wake_alarm_->Schedule(
- common::BindOnce(&impl::set_advertising_set_random_address_on_timer,
- common::Unretained(this), id),
- privateAddressIntervalRange.min);
-
- // Update the expected range here.
- auto now = std::chrono::system_clock::now();
- advertising_sets_[id].address_rotation_interval_min.emplace(
- now + privateAddressIntervalRange.min);
- advertising_sets_[id].address_rotation_interval_max.emplace(
- now + privateAddressIntervalRange.max);
- } else {
- advertising_sets_[id].address_rotation_wake_alarm_ =
- std::make_unique<os::Alarm>(module_handler_);
- advertising_sets_[id].address_rotation_wake_alarm_->Schedule(
- common::BindOnce(&impl::set_advertising_set_random_address_on_timer,
- common::Unretained(this), id),
- le_address_manager_->GetNextPrivateAddressIntervalMs());
- }
+ advertising_sets_[id].address_rotation_wake_alarm_ =
+ std::make_unique<os::Alarm>(module_handler_, true);
+ advertising_sets_[id].address_rotation_non_wake_alarm_ =
+ std::make_unique<os::Alarm>(module_handler_, false);
+
+ std::string client_name = "advertising_set_" + std::to_string(id);
+ auto privateAddressIntervalRange =
+ le_address_manager_->GetNextPrivateAddressIntervalRange(client_name);
+
+ advertising_sets_[id].address_rotation_wake_alarm_->Schedule(
+ common::BindOnce([]() {
+ log::info("deadline wakeup in create_extended_advertiser_with_id");
+ }),
+ privateAddressIntervalRange.max);
+ advertising_sets_[id].address_rotation_non_wake_alarm_->Schedule(
+ common::BindOnce(&impl::set_advertising_set_random_address_on_timer,
+ common::Unretained(this), id),
+ privateAddressIntervalRange.min);
+
+ // Update the expected range here.
+ auto now = std::chrono::system_clock::now();
+ advertising_sets_[id].address_rotation_interval_min.emplace(
+ now + privateAddressIntervalRange.min);
+ advertising_sets_[id].address_rotation_interval_max.emplace(
+ now + privateAddressIntervalRange.max);
}
}
if (config.advertising_type == AdvertisingType::ADV_IND ||
@@ -859,39 +840,31 @@ struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallb
}
log::info("Scheduling address rotation for advertiser_id={}", advertiser_id);
- if (com::android::bluetooth::flags::non_wake_alarm_for_rpa_rotation()) {
- std::string client_name = "advertising_set_" + std::to_string(advertiser_id);
- auto privateAddressIntervalRange =
- le_address_manager_->GetNextPrivateAddressIntervalRange(client_name);
- advertising_sets_[advertiser_id].address_rotation_wake_alarm_->Schedule(
- common::BindOnce([]() {
- log::info("deadline wakeup in set_advertising_set_random_address_on_timer");
- }),
- privateAddressIntervalRange.max);
- advertising_sets_[advertiser_id].address_rotation_non_wake_alarm_->Schedule(
- common::BindOnce(&impl::set_advertising_set_random_address_on_timer,
- common::Unretained(this), advertiser_id),
- privateAddressIntervalRange.min);
-
- auto now = std::chrono::system_clock::now();
- if (advertising_sets_[advertiser_id].address_rotation_interval_min.has_value()) {
- le_address_manager_->CheckAddressRotationHappenedInExpectedTimeInterval(
- *(advertising_sets_[advertiser_id].address_rotation_interval_min),
- *(advertising_sets_[advertiser_id].address_rotation_interval_max), now,
- client_name);
- }
-
- // Update the expected range here.
- advertising_sets_[advertiser_id].address_rotation_interval_min.emplace(
- now + privateAddressIntervalRange.min);
- advertising_sets_[advertiser_id].address_rotation_interval_max.emplace(
- now + privateAddressIntervalRange.max);
- } else {
- advertising_sets_[advertiser_id].address_rotation_wake_alarm_->Schedule(
- common::BindOnce(&impl::set_advertising_set_random_address_on_timer,
- common::Unretained(this), advertiser_id),
- le_address_manager_->GetNextPrivateAddressIntervalMs());
+ std::string client_name = "advertising_set_" + std::to_string(advertiser_id);
+ auto privateAddressIntervalRange =
+ le_address_manager_->GetNextPrivateAddressIntervalRange(client_name);
+ advertising_sets_[advertiser_id].address_rotation_wake_alarm_->Schedule(
+ common::BindOnce([]() {
+ log::info("deadline wakeup in set_advertising_set_random_address_on_timer");
+ }),
+ privateAddressIntervalRange.max);
+ advertising_sets_[advertiser_id].address_rotation_non_wake_alarm_->Schedule(
+ common::BindOnce(&impl::set_advertising_set_random_address_on_timer,
+ common::Unretained(this), advertiser_id),
+ privateAddressIntervalRange.min);
+
+ auto now = std::chrono::system_clock::now();
+ if (advertising_sets_[advertiser_id].address_rotation_interval_min.has_value()) {
+ le_address_manager_->CheckAddressRotationHappenedInExpectedTimeInterval(
+ *(advertising_sets_[advertiser_id].address_rotation_interval_min),
+ *(advertising_sets_[advertiser_id].address_rotation_interval_max), now, client_name);
}
+
+ // Update the expected range here.
+ advertising_sets_[advertiser_id].address_rotation_interval_min.emplace(
+ now + privateAddressIntervalRange.min);
+ advertising_sets_[advertiser_id].address_rotation_interval_max.emplace(
+ now + privateAddressIntervalRange.max);
}
void register_advertiser(
diff --git a/system/gd/metrics/chromeos/OWNERS b/system/gd/metrics/chromeos/OWNERS
deleted file mode 100644
index a823e6e1dd..0000000000
--- a/system/gd/metrics/chromeos/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_chromeos
diff --git a/system/gd/metrics/counter_metrics.h b/system/gd/metrics/counter_metrics.h
index 88c7711f92..2f25f03ed0 100644
--- a/system/gd/metrics/counter_metrics.h
+++ b/system/gd/metrics/counter_metrics.h
@@ -15,6 +15,8 @@
*/
#pragma once
+#include <com_android_bluetooth_flags.h>
+
#include <unordered_map>
#include "module.h"
@@ -26,6 +28,13 @@ namespace metrics {
class CounterMetrics : public bluetooth::Module {
public:
CounterMetrics(os::Handler* handler) : Module(handler) {}
+ ~CounterMetrics() {
+ if (!com::android::bluetooth::flags::same_handler_for_all_modules()) {
+ GetHandler()->Clear();
+ GetHandler()->WaitUntilStopped(std::chrono::milliseconds(2000));
+ delete GetHandler();
+ }
+ }
bool CacheCount(int32_t key, int64_t value);
virtual bool Count(int32_t key, int64_t count);
diff --git a/system/gd/metrics/linux/OWNERS b/system/gd/metrics/linux/OWNERS
deleted file mode 100644
index a823e6e1dd..0000000000
--- a/system/gd/metrics/linux/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_chromeos
diff --git a/system/gd/module.cc b/system/gd/module.cc
index 8904f0c559..76b386bbfe 100644
--- a/system/gd/module.cc
+++ b/system/gd/module.cc
@@ -128,10 +128,18 @@ void ModuleRegistry::StopAll() {
auto module = Get(*it);
last_instance_ = "stopping " + module->ToString();
- // Clear the handler before stopping the module to allow it to shut down gracefully.
- log::info("Stopping Handler of Module {}", module->ToString());
- module->handler_->Clear();
- module->handler_->WaitUntilStopped(kModuleStopTimeout);
+ /*
+ * b/393449774 since we have now shifted to a single handler for all modules, we don't need
+ * to clear the handler here, it will be done in the respective teardown.
+ * Since we have a single handler, we need to make sure that the handler instance is deleted
+ * only once, otherwise we will see a crash as a handler can only be cleared once.
+ */
+ if (!com::android::bluetooth::flags::same_handler_for_all_modules()) {
+ // Clear the handler before stopping the module to allow it to shut down gracefully.
+ log::info("Stopping Handler of Module {}", module->ToString());
+ module->handler_->Clear();
+ module->handler_->WaitUntilStopped(kModuleStopTimeout);
+ }
log::info("Stopping Module {}", module->ToString());
module->Stop();
}
@@ -144,7 +152,9 @@ void ModuleRegistry::StopAll() {
auto instance = started_modules_.find(*it);
log::assert_that(instance != started_modules_.end(),
"assert failed: instance != started_modules_.end()");
- delete instance->second->handler_;
+ if (!com::android::bluetooth::flags::same_handler_for_all_modules()) {
+ delete instance->second->handler_;
+ }
delete instance->second;
started_modules_.erase(instance);
}
@@ -165,4 +175,15 @@ os::Handler* ModuleRegistry::GetModuleHandler(const ModuleFactory* module) const
return nullptr;
}
+// Override the StopAll method to use the test thread and handler.
+// This function will take care of releasing the handler instances.
+void TestModuleRegistry::StopAll() {
+ os::Handler* handler = GetTestHandler();
+ handler->Clear();
+ if (com::android::bluetooth::flags::same_handler_for_all_modules()) {
+ handler->WaitUntilStopped(kHandlerStopTimeout);
+ }
+ ModuleRegistry::StopAll(); // call the base class StopAll
+ delete handler;
+}
} // namespace bluetooth
diff --git a/system/gd/module.h b/system/gd/module.h
index 816d455482..57e4db7d16 100644
--- a/system/gd/module.h
+++ b/system/gd/module.h
@@ -32,6 +32,9 @@
#include "os/thread.h"
namespace bluetooth {
+// Timeout for waiting for a handler to stop, used in Handler::WaitUntilStopped()
+constexpr std::chrono::milliseconds kHandlerStopTimeout = std::chrono::milliseconds(2000);
+
namespace shim {
class Stack;
} // namespace shim
@@ -191,6 +194,9 @@ public:
os::Thread& GetTestThread() { return test_thread; }
os::Handler* GetTestHandler() { return test_handler_; }
+ // Override the StopAll method to use the test thread and handler.
+ void StopAll();
+
bool SynchronizeModuleHandler(const ModuleFactory* module,
std::chrono::milliseconds timeout) const {
return SynchronizeHandler(GetTestModuleHandler(module), timeout);
diff --git a/system/gd/module_unittest.cc b/system/gd/module_unittest.cc
index d1bf59ac73..8fb140c229 100644
--- a/system/gd/module_unittest.cc
+++ b/system/gd/module_unittest.cc
@@ -22,6 +22,7 @@
#include <sstream>
#include <string>
+#include "com_android_bluetooth_flags.h"
#include "gtest/gtest.h"
#include "os/handler.h"
#include "os/thread.h"
@@ -41,9 +42,12 @@ protected:
void TearDown() override {
handler_->Clear();
+ if (com::android::bluetooth::flags::same_handler_for_all_modules()) {
+ handler_->WaitUntilStopped(kHandlerStopTimeout);
+ }
delete registry_;
- delete thread_;
delete handler_;
+ delete thread_;
}
ModuleRegistry* registry_;
diff --git a/system/gd/os/android/metrics.cc b/system/gd/os/android/metrics.cc
index 78b12c8d96..5f5b34ef2e 100644
--- a/system/gd/os/android/metrics.cc
+++ b/system/gd/os/android/metrics.cc
@@ -122,11 +122,9 @@ void LogMetricRemoteVersionInfo(uint16_t handle, uint8_t status, uint8_t version
manufacturer_name, subversion);
if (ret < 0) {
log::warn(
- "Failed for handle {}, status {}, version {}, manufacturer_name {}, subversion {}, "
- "error "
- "{}",
- handle, common::ToHexString(status), common::ToHexString(version),
- common::ToHexString(manufacturer_name), common::ToHexString(subversion), ret);
+ "failed for handle {}, status 0x{:x}, version 0x{:x}, "
+ "manufacturer_name 0x{:x}, subversion 0x{:x}, error {}",
+ handle, status, version, manufacturer_name, subversion, ret);
}
}
@@ -526,5 +524,53 @@ void LogMetricRfcommConnectionAtClose(const Address& address,
}
}
+void LogMetricLeAudioConnectionSessionReported(
+ int32_t group_size, int32_t group_metric_id, int64_t connection_duration_nanos,
+ const std::vector<int64_t>& device_connecting_offset_nanos,
+ const std::vector<int64_t>& device_connected_offset_nanos,
+ const std::vector<int64_t>& device_connection_duration_nanos,
+ const std::vector<int32_t>& device_connection_status,
+ const std::vector<int32_t>& device_disconnection_status,
+ const std::vector<RawAddress>& device_address,
+ const std::vector<int64_t>& streaming_offset_nanos,
+ const std::vector<int64_t>& streaming_duration_nanos,
+ const std::vector<int32_t>& streaming_context_type) {
+ std::vector<int32_t> device_metric_id(device_address.size());
+ for (uint64_t i = 0; i < device_address.size(); i++) {
+ if (!device_address[i].IsEmpty()) {
+ device_metric_id[i] =
+ MetricIdManager::GetInstance().AllocateId(ToGdAddress(device_address[i]));
+ } else {
+ device_metric_id[i] = 0;
+ }
+ }
+ int ret = stats_write(LE_AUDIO_CONNECTION_SESSION_REPORTED, group_size, group_metric_id,
+ connection_duration_nanos, device_connecting_offset_nanos,
+ device_connected_offset_nanos, device_connection_duration_nanos,
+ device_connection_status, device_disconnection_status, device_metric_id,
+ streaming_offset_nanos, streaming_duration_nanos, streaming_context_type);
+ if (ret < 0) {
+ log::warn(
+ "failed for group {}device_connecting_offset_nanos[{}], "
+ "device_connected_offset_nanos[{}], "
+ "device_connection_duration_nanos[{}], device_connection_status[{}], "
+ "device_disconnection_status[{}], device_metric_id[{}], "
+ "streaming_offset_nanos[{}], streaming_duration_nanos[{}], "
+ "streaming_context_type[{}]",
+ group_metric_id, device_connecting_offset_nanos.size(),
+ device_connected_offset_nanos.size(), device_connection_duration_nanos.size(),
+ device_connection_status.size(), device_disconnection_status.size(),
+ device_metric_id.size(), streaming_offset_nanos.size(), streaming_duration_nanos.size(),
+ streaming_context_type.size());
+ }
+}
+
+void LogMetricLeAudioBroadcastSessionReported(int64_t duration_nanos) {
+ int ret = stats_write(LE_AUDIO_BROADCAST_SESSION_REPORTED, duration_nanos);
+ if (ret < 0) {
+ log::warn("failed for duration={}", duration_nanos);
+ }
+}
+
} // namespace os
} // namespace bluetooth
diff --git a/system/gd/os/chromeos/metrics.cc b/system/gd/os/chromeos/metrics.cc
index b7921fe308..de36a98780 100644
--- a/system/gd/os/chromeos/metrics.cc
+++ b/system/gd/os/chromeos/metrics.cc
@@ -216,5 +216,19 @@ void LogMetricRfcommConnectionAtClose(
android::bluetooth::BtaStatus /* sdp_status */, bool /* is_server */,
bool /* sdp_initiated */, int32_t /* sdp_duration_ms */) {}
+void LogMetricLeAudioConnectionSessionReported(
+ int32_t /*group_size*/, int32_t /*group_metric_id*/, int64_t /*connection_duration_nanos*/,
+ const std::vector<int64_t>& /*device_connecting_offset_nanos*/,
+ const std::vector<int64_t>& /*device_connected_offset_nanos*/,
+ const std::vector<int64_t>& /*device_connection_duration_nanos*/,
+ const std::vector<int32_t>& /*device_connection_status*/,
+ const std::vector<int32_t>& /*device_disconnection_status*/,
+ const std::vector<RawAddress>& /*device_address*/,
+ const std::vector<int64_t>& /*streaming_offset_nanos*/,
+ const std::vector<int64_t>& /*streaming_duration_nanos*/,
+ const std::vector<int32_t>& /*streaming_context_type*/) {}
+
+void LogMetricLeAudioBroadcastSessionReported(int64_t /*duration_nanos*/) {}
+
} // namespace os
} // namespace bluetooth
diff --git a/system/gd/os/host/metrics.cc b/system/gd/os/host/metrics.cc
index a333113238..518a29ffee 100644
--- a/system/gd/os/host/metrics.cc
+++ b/system/gd/os/host/metrics.cc
@@ -135,5 +135,19 @@ void LogMetricRfcommConnectionAtClose(
android::bluetooth::BtaStatus /* sdp_status */, bool /* is_server */,
bool /* sdp_initiated */, int32_t /* sdp_duration_ms */) {}
+void LogMetricLeAudioConnectionSessionReported(
+ int32_t /*group_size*/, int32_t /*group_metric_id*/, int64_t /*connection_duration_nanos*/,
+ const std::vector<int64_t>& /*device_connecting_offset_nanos*/,
+ const std::vector<int64_t>& /*device_connected_offset_nanos*/,
+ const std::vector<int64_t>& /*device_connection_duration_nanos*/,
+ const std::vector<int32_t>& /*device_connection_status*/,
+ const std::vector<int32_t>& /*device_disconnection_status*/,
+ const std::vector<RawAddress>& /*device_address*/,
+ const std::vector<int64_t>& /*streaming_offset_nanos*/,
+ const std::vector<int64_t>& /*streaming_duration_nanos*/,
+ const std::vector<int32_t>& /*streaming_context_type*/) {}
+
+void LogMetricLeAudioBroadcastSessionReported(int64_t /*duration_nanos*/) {}
+
} // namespace os
} // namespace bluetooth
diff --git a/system/gd/os/linux/metrics.cc b/system/gd/os/linux/metrics.cc
index 7b727f38f2..f5d1555075 100644
--- a/system/gd/os/linux/metrics.cc
+++ b/system/gd/os/linux/metrics.cc
@@ -122,5 +122,20 @@ void LogMetricRfcommConnectionAtClose(const Address& raw_address,
void LogMetricBluetoothEvent(const Address& address, android::bluetooth::EventType event_type,
android::bluetooth::State state) {}
+
+void LogMetricLeAudioConnectionSessionReported(
+ int32_t /*group_size*/, int32_t /*group_metric_id*/, int64_t /*connection_duration_nanos*/,
+ const std::vector<int64_t>& /*device_connecting_offset_nanos*/,
+ const std::vector<int64_t>& /*device_connected_offset_nanos*/,
+ const std::vector<int64_t>& /*device_connection_duration_nanos*/,
+ const std::vector<int32_t>& /*device_connection_status*/,
+ const std::vector<int32_t>& /*device_disconnection_status*/,
+ const std::vector<RawAddress>& /*device_address*/,
+ const std::vector<int64_t>& /*streaming_offset_nanos*/,
+ const std::vector<int64_t>& /*streaming_duration_nanos*/,
+ const std::vector<int32_t>& /*streaming_context_type*/) {}
+
+void LogMetricLeAudioBroadcastSessionReported(int64_t /*duration_nanos*/) {}
+
} // namespace os
} // namespace bluetooth
diff --git a/system/gd/os/linux_generic/alarm.cc b/system/gd/os/linux_generic/alarm.cc
index 8846ede579..a378ca93cd 100644
--- a/system/gd/os/linux_generic/alarm.cc
+++ b/system/gd/os/linux_generic/alarm.cc
@@ -17,7 +17,6 @@
#include "os/alarm.h"
#include <bluetooth/log.h>
-#include <com_android_bluetooth_flags.h>
#include <sys/timerfd.h>
#include <unistd.h>
@@ -41,8 +40,7 @@ using common::OnceClosure;
Alarm::Alarm(Handler* handler) : Alarm(handler, true) {}
Alarm::Alarm(Handler* handler, bool isWakeAlarm) : handler_(handler) {
- int timerfd_flag =
- com::android::bluetooth::flags::non_wake_alarm_for_rpa_rotation() ? TFD_NONBLOCK : 0;
+ int timerfd_flag = TFD_NONBLOCK;
fd_ = TIMERFD_CREATE(isWakeAlarm ? ALARM_CLOCK : CLOCK_BOOTTIME, timerfd_flag);
@@ -85,7 +83,7 @@ void Alarm::on_fire() {
auto bytes_read = read(fd_, &times_invoked, sizeof(uint64_t));
lock.unlock();
- if (com::android::bluetooth::flags::non_wake_alarm_for_rpa_rotation() && bytes_read == -1) {
+ if (bytes_read == -1) {
log::debug("No data to read.");
if (errno == EAGAIN || errno == EWOULDBLOCK) {
log::debug("Alarm is already canceled or rescheduled.");
diff --git a/system/gd/os/metrics.h b/system/gd/os/metrics.h
index aab82826e6..04b5c37e84 100644
--- a/system/gd/os/metrics.h
+++ b/system/gd/os/metrics.h
@@ -29,8 +29,8 @@
#include "types/raw_address.h"
namespace bluetooth {
-
namespace os {
+
/**
* Unknown connection handle for metrics purpose
*/
@@ -379,6 +379,19 @@ void LogMetricRfcommConnectionAtClose(const hci::Address& address,
android::bluetooth::BtaStatus sdp_status, bool is_server,
bool sdp_initiated, int32_t sdp_duration_ms);
+void LogMetricLeAudioConnectionSessionReported(
+ int32_t group_size, int32_t group_metric_id, int64_t connection_duration_nanos,
+ const std::vector<int64_t>& device_connecting_offset_nanos,
+ const std::vector<int64_t>& device_connected_offset_nanos,
+ const std::vector<int64_t>& device_connection_duration_nanos,
+ const std::vector<int32_t>& device_connection_status,
+ const std::vector<int32_t>& device_disconnection_status,
+ const std::vector<RawAddress>& device_address,
+ const std::vector<int64_t>& streaming_offset_nanos,
+ const std::vector<int64_t>& streaming_duration_nanos,
+ const std::vector<int32_t>& streaming_context_type);
+
+void LogMetricLeAudioBroadcastSessionReported(int64_t duration_nanos);
+
} // namespace os
- //
} // namespace bluetooth
diff --git a/system/gd/rust/linux/OWNERS b/system/gd/rust/linux/OWNERS
deleted file mode 100644
index a823e6e1dd..0000000000
--- a/system/gd/rust/linux/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_chromeos
diff --git a/system/gd/rust/linux/service/src/interface_manager.rs b/system/gd/rust/linux/service/src/interface_manager.rs
index 116979de0d..62fdbc8638 100644
--- a/system/gd/rust/linux/service/src/interface_manager.rs
+++ b/system/gd/rust/linux/service/src/interface_manager.rs
@@ -1,27 +1,29 @@
-use dbus::{channel::MatchingReceiver, message::MatchRule, nonblock::SyncConnection};
+use dbus::channel::MatchingReceiver;
+use dbus::message::MatchRule;
+use dbus::nonblock::SyncConnection;
use dbus_crossroads::Crossroads;
use dbus_projection::DisconnectWatcher;
use std::sync::{Arc, Mutex};
use tokio::sync::mpsc::{channel, Receiver, Sender};
-use btstack::{
- battery_manager::BatteryManager, battery_provider_manager::BatteryProviderManager,
- bluetooth::Bluetooth, bluetooth_admin::BluetoothAdmin, bluetooth_gatt::BluetoothGatt,
- bluetooth_logging::BluetoothLogging, bluetooth_media::BluetoothMedia,
- bluetooth_qa::BluetoothQA, socket_manager::BluetoothSocketManager, suspend::Suspend,
- APIMessage, BluetoothAPI, Message,
-};
+use btstack::battery_manager::BatteryManager;
+use btstack::battery_provider_manager::BatteryProviderManager;
+use btstack::bluetooth::{Bluetooth, SigData};
+use btstack::bluetooth_admin::BluetoothAdmin;
+use btstack::bluetooth_gatt::BluetoothGatt;
+use btstack::bluetooth_logging::BluetoothLogging;
+use btstack::bluetooth_media::BluetoothMedia;
+use btstack::bluetooth_qa::BluetoothQA;
+use btstack::socket_manager::BluetoothSocketManager;
+use btstack::suspend::Suspend;
+use btstack::{APIMessage, BluetoothAPI};
-use crate::iface_battery_manager;
-use crate::iface_battery_provider_manager;
-use crate::iface_bluetooth;
-use crate::iface_bluetooth_admin;
-use crate::iface_bluetooth_gatt;
-use crate::iface_bluetooth_media;
-use crate::iface_bluetooth_qa;
-use crate::iface_bluetooth_telephony;
-use crate::iface_logging;
+use crate::{
+ iface_battery_manager, iface_battery_provider_manager, iface_bluetooth, iface_bluetooth_admin,
+ iface_bluetooth_gatt, iface_bluetooth_media, iface_bluetooth_qa, iface_bluetooth_telephony,
+ iface_logging,
+};
pub(crate) struct InterfaceManager {}
@@ -50,11 +52,11 @@ impl InterfaceManager {
#[allow(clippy::too_many_arguments)]
pub async fn dispatch(
mut rx: Receiver<APIMessage>,
- tx: Sender<Message>,
virt_index: i32,
conn: Arc<SyncConnection>,
conn_join_handle: tokio::task::JoinHandle<()>,
disconnect_watcher: Arc<Mutex<DisconnectWatcher>>,
+ sig_notifier: Arc<SigData>,
bluetooth: Arc<Mutex<Box<Bluetooth>>>,
bluetooth_admin: Arc<Mutex<Box<BluetoothAdmin>>>,
bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>,
@@ -93,6 +95,9 @@ impl InterfaceManager {
}),
);
+ *sig_notifier.api_enabled.lock().unwrap() = true;
+ sig_notifier.api_notify.notify_all();
+
// Register D-Bus method handlers of IBluetooth.
let adapter_iface = iface_bluetooth::export_bluetooth_dbus_intf(
conn.clone(),
@@ -246,11 +251,8 @@ impl InterfaceManager {
// To shut down the connection, call _handle.abort() and drop the connection.
conn_join_handle.abort();
drop(conn);
-
- let tx = tx.clone();
- tokio::spawn(async move {
- let _ = tx.send(Message::AdapterShutdown).await;
- });
+ *sig_notifier.api_enabled.lock().unwrap() = false;
+ sig_notifier.api_notify.notify_all();
break;
}
}
diff --git a/system/gd/rust/linux/service/src/main.rs b/system/gd/rust/linux/service/src/main.rs
index f326bb62ee..4fc43d11f3 100644
--- a/system/gd/rust/linux/service/src/main.rs
+++ b/system/gd/rust/linux/service/src/main.rs
@@ -9,22 +9,21 @@ use std::time::Duration;
use tokio::runtime::Builder;
use tokio::sync::mpsc::Sender;
-use bt_topshim::{btif::get_btinterface, topstack};
-use btstack::{
- battery_manager::BatteryManager,
- battery_provider_manager::BatteryProviderManager,
- battery_service::BatteryService,
- bluetooth::{Bluetooth, IBluetooth, SigData},
- bluetooth_admin::BluetoothAdmin,
- bluetooth_gatt::BluetoothGatt,
- bluetooth_logging::BluetoothLogging,
- bluetooth_media::BluetoothMedia,
- bluetooth_qa::BluetoothQA,
- dis::DeviceInformation,
- socket_manager::BluetoothSocketManager,
- suspend::Suspend,
- Message, Stack,
-};
+use bt_topshim::btif::get_btinterface;
+use bt_topshim::topstack;
+use btstack::battery_manager::BatteryManager;
+use btstack::battery_provider_manager::BatteryProviderManager;
+use btstack::battery_service::BatteryService;
+use btstack::bluetooth::{Bluetooth, IBluetooth, SigData};
+use btstack::bluetooth_admin::BluetoothAdmin;
+use btstack::bluetooth_gatt::BluetoothGatt;
+use btstack::bluetooth_logging::BluetoothLogging;
+use btstack::bluetooth_media::BluetoothMedia;
+use btstack::bluetooth_qa::BluetoothQA;
+use btstack::dis::DeviceInformation;
+use btstack::socket_manager::BluetoothSocketManager;
+use btstack::suspend::Suspend;
+use btstack::{Message, Stack};
mod dbus_arg;
mod iface_battery_manager;
@@ -40,6 +39,8 @@ mod interface_manager;
const DBUS_SERVICE_NAME: &str = "org.chromium.bluetooth";
const ADMIN_SETTINGS_FILE_PATH: &str = "/var/lib/bluetooth/admin_policy.json";
+// Time to wait for API unregistration in DBus
+const API_DISABLE_TIMEOUT_MS: Duration = Duration::from_millis(100);
// The maximum ACL disconnect timeout is 3.5s defined by BTA_DM_DISABLE_TIMER_MS
// and BTA_DM_DISABLE_TIMER_RETRIAL_MS
const STACK_TURN_OFF_TIMEOUT_MS: Duration = Duration::from_millis(4000);
@@ -115,6 +116,8 @@ fn main() -> Result<(), Box<dyn Error>> {
enabled_notify: Condvar::new(),
thread_attached: Mutex::new(false),
thread_notify: Condvar::new(),
+ api_enabled: Mutex::new(false),
+ api_notify: Condvar::new(),
});
// This needs to be built before any |topstack::get_runtime()| call!
@@ -148,8 +151,14 @@ fn main() -> Result<(), Box<dyn Error>> {
signal::SaFlags::empty(),
signal::SigSet::empty(),
);
+ let sig_action_usr1 = signal::SigAction::new(
+ signal::SigHandler::Handler(handle_sigusr1),
+ signal::SaFlags::empty(),
+ signal::SigSet::empty(),
+ );
unsafe {
signal::sigaction(signal::SIGTERM, &sig_action_term).unwrap();
+ signal::sigaction(signal::SIGUSR1, &sig_action_usr1).unwrap();
}
// Construct btstack profiles.
@@ -241,11 +250,11 @@ fn main() -> Result<(), Box<dyn Error>> {
tokio::spawn(interface_manager::InterfaceManager::dispatch(
api_rx,
- tx.clone(),
virt_index,
conn,
conn_join_handle,
disconnect_watcher.clone(),
+ sig_notifier.clone(),
bluetooth.clone(),
bluetooth_admin.clone(),
bluetooth_gatt.clone(),
@@ -267,37 +276,63 @@ fn main() -> Result<(), Box<dyn Error>> {
/// Data needed for signal handling.
static SIG_DATA: Mutex<Option<(Sender<Message>, Arc<SigData>)>> = Mutex::new(None);
-extern "C" fn handle_sigterm(_signum: i32) {
- let guard = SIG_DATA.lock().unwrap();
- if let Some((tx, notifier)) = guard.as_ref() {
- log::debug!("Handling SIGTERM by disabling the adapter!");
- let txl = tx.clone();
- topstack::get_runtime().spawn(async move {
- // Send the shutdown message here.
- let _ = txl.send(Message::InterfaceShutdown).await;
- });
+/// Try to cleanup the whole stack. Returns whether to clean up.
+extern "C" fn try_cleanup_stack(abort: bool) -> bool {
+ let lock = SIG_DATA.try_lock();
+
+ // If SIG_DATA is locked, it is likely the cleanup procedure is ongoing. No
+ // need to do anything here.
+ if lock.is_err() {
+ return false;
+ }
+
+ if let Some((tx, notifier)) = lock.unwrap().as_ref() {
+ log::info!("Cleanup stack: disabling the adapter!");
+
+ // Remove the API first to prevent clients calling while shutting down.
+ let guard = notifier.api_enabled.lock().unwrap();
+ if *guard {
+ let txl = tx.clone();
+ topstack::get_runtime().spawn(async move {
+ // Remove the API first to prevent clients calling while shutting down.
+ let _ = txl.send(Message::InterfaceShutdown).await;
+ });
+ log::info!(
+ "Cleanup stack: Waiting for API shutdown to complete for {:?}",
+ API_DISABLE_TIMEOUT_MS
+ );
+ let _ = notifier.api_notify.wait_timeout(guard, API_DISABLE_TIMEOUT_MS);
+ }
let guard = notifier.enabled.lock().unwrap();
if *guard {
- log::debug!("Waiting for stack to turn off for {:?}", STACK_TURN_OFF_TIMEOUT_MS);
+ let txl = tx.clone();
+ topstack::get_runtime().spawn(async move {
+ let _ = txl.send(Message::AdapterShutdown(abort)).await;
+ });
+ log::info!(
+ "Cleanup stack: Waiting for stack to turn off for {:?}",
+ STACK_TURN_OFF_TIMEOUT_MS
+ );
let _ = notifier.enabled_notify.wait_timeout(guard, STACK_TURN_OFF_TIMEOUT_MS);
}
- log::debug!("SIGTERM cleaning up the stack.");
- let txl = tx.clone();
- topstack::get_runtime().spawn(async move {
- // Clean up the profiles first as some of them might require main thread to clean up.
- let _ = txl.send(Message::CleanupProfiles).await;
- // Currently there is no good way to know when the profile is cleaned.
- // Simply add a small delay here.
- tokio::time::sleep(STACK_CLEANUP_PROFILES_TIMEOUT_MS).await;
- // Send the cleanup message to clean up the main thread.
- let _ = txl.send(Message::Cleanup).await;
- });
-
let guard = notifier.thread_attached.lock().unwrap();
if *guard {
- log::debug!("Waiting for stack to clean up for {:?}", STACK_CLEANUP_TIMEOUT_MS);
+ let txl = tx.clone();
+ topstack::get_runtime().spawn(async move {
+ // Clean up the profiles first as some of them might require main thread to clean up.
+ let _ = txl.send(Message::CleanupProfiles).await;
+ // Currently there is no good way to know when the profile is cleaned.
+ // Simply add a small delay here.
+ tokio::time::sleep(STACK_CLEANUP_PROFILES_TIMEOUT_MS).await;
+ // Send the cleanup message to clean up the main thread.
+ let _ = txl.send(Message::Cleanup).await;
+ });
+ log::info!(
+ "Cleanup stack: Waiting for libbluetooth stack to clean up for {:?}",
+ STACK_CLEANUP_TIMEOUT_MS
+ );
let _ = notifier.thread_notify.wait_timeout(guard, STACK_CLEANUP_TIMEOUT_MS);
}
@@ -305,7 +340,26 @@ extern "C" fn handle_sigterm(_signum: i32) {
// finishing btif cleanup.
std::thread::sleep(EXTRA_WAIT_BEFORE_KILL_MS);
}
+ return true;
+}
- log::debug!("Sigterm completed");
+extern "C" fn handle_sigterm(_signum: i32) {
+ log::info!("SIGTERM received");
+ if !try_cleanup_stack(false) {
+ log::info!("Skipped to handle SIGTERM");
+ return;
+ }
+ log::info!("SIGTERM completed");
+ std::process::exit(0);
+}
+
+/// Used to indicate controller needs reset
+extern "C" fn handle_sigusr1(_signum: i32) {
+ log::info!("SIGUSR1 received");
+ if !try_cleanup_stack(true) {
+ log::info!("Skipped to handle SIGUSR1");
+ return;
+ }
+ log::info!("SIGUSR1 completed");
std::process::exit(0);
}
diff --git a/system/gd/rust/linux/stack/src/bluetooth.rs b/system/gd/rust/linux/stack/src/bluetooth.rs
index bac9c4a1a9..ade91229c4 100644
--- a/system/gd/rust/linux/stack/src/bluetooth.rs
+++ b/system/gd/rust/linux/stack/src/bluetooth.rs
@@ -503,6 +503,9 @@ pub struct SigData {
pub thread_attached: Mutex<bool>,
pub thread_notify: Condvar,
+
+ pub api_enabled: Mutex<bool>,
+ pub api_notify: Condvar,
}
/// The interface for adapter callbacks registered through `IBluetooth::register_callback`.
@@ -818,6 +821,21 @@ impl Bluetooth {
self.connection_callbacks.remove_callback(id);
}
+ pub fn shutdown_adapter(&mut self, abort: bool) -> bool {
+ self.disabling = true;
+
+ if !abort {
+ if !self.set_discoverable(BtDiscMode::NonDiscoverable, 0) {
+ warn!("set_discoverable failed on disabling");
+ }
+ if !self.set_connectable_internal(false) {
+ warn!("set_connectable_internal failed on disabling");
+ }
+ }
+
+ self.intf.lock().unwrap().disable() == 0
+ }
+
fn get_remote_device_property(
&self,
device: &BluetoothDevice,
@@ -2240,14 +2258,7 @@ impl IBluetooth for Bluetooth {
}
fn disable(&mut self) -> bool {
- self.disabling = true;
- if !self.set_discoverable(BtDiscMode::NonDiscoverable, 0) {
- warn!("set_discoverable failed on disabling");
- }
- if !self.set_connectable_internal(false) {
- warn!("set_connectable_internal failed on disabling");
- }
- self.intf.lock().unwrap().disable() == 0
+ self.shutdown_adapter(false)
}
fn cleanup(&mut self) {
diff --git a/system/gd/rust/linux/stack/src/lib.rs b/system/gd/rust/linux/stack/src/lib.rs
index d9f97bfa32..4f49a186b4 100644
--- a/system/gd/rust/linux/stack/src/lib.rs
+++ b/system/gd/rust/linux/stack/src/lib.rs
@@ -66,7 +66,9 @@ pub enum Message {
/// Remove the DBus API. Call it before other AdapterShutdown.
InterfaceShutdown,
/// Disable the adapter by calling btif disable.
- AdapterShutdown,
+ /// Param: bool to indicate abort(true) or graceful shutdown(false).
+ /// Use abort when we believe adapter is already in a bad state.
+ AdapterShutdown(bool),
/// Clean up the adapter by calling btif cleanup.
Cleanup,
/// Clean up the media by calling profile cleanup.
@@ -287,9 +289,9 @@ impl Stack {
});
}
- Message::AdapterShutdown => {
+ Message::AdapterShutdown(abort) => {
bluetooth_gatt.lock().unwrap().enable(false);
- bluetooth.lock().unwrap().disable();
+ bluetooth.lock().unwrap().shutdown_adapter(abort);
}
Message::Cleanup => {
diff --git a/system/gd/rust/topshim/OWNERS b/system/gd/rust/topshim/OWNERS
deleted file mode 100644
index a823e6e1dd..0000000000
--- a/system/gd/rust/topshim/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_chromeos
diff --git a/system/gd/storage/storage_module.cc b/system/gd/storage/storage_module.cc
index 5e3459e109..5a81a5cf94 100644
--- a/system/gd/storage/storage_module.cc
+++ b/system/gd/storage/storage_module.cc
@@ -90,6 +90,13 @@ StorageModule::StorageModule(os::Handler* handler, std::string config_file_path,
StorageModule::~StorageModule() {
std::lock_guard<std::recursive_mutex> lock(mutex_);
+
+ if (!com::android::bluetooth::flags::same_handler_for_all_modules()) {
+ GetHandler()->Clear();
+ GetHandler()->WaitUntilStopped(std::chrono::milliseconds(2000));
+ delete GetHandler();
+ }
+
pimpl_.reset();
}
diff --git a/system/include/hardware/bluetooth_headset_interface.h b/system/include/hardware/bluetooth_headset_interface.h
index b2b98ffe1f..396c2b2880 100644
--- a/system/include/hardware/bluetooth_headset_interface.h
+++ b/system/include/hardware/bluetooth_headset_interface.h
@@ -97,9 +97,10 @@ public:
/**
* Start voice recognition
* @param bd_addr remote device address
+ * @param sendResult whether a BVRA response should be sent
* @return BT_STATUS_SUCCESS on success
*/
- virtual bt_status_t StartVoiceRecognition(RawAddress* bd_addr) = 0;
+ virtual bt_status_t StartVoiceRecognition(RawAddress* bd_addr, bool sendResult) = 0;
/**
* Stop voice recognition
diff --git a/system/linux_include/log/log.h b/system/linux_include/log/log.h
deleted file mode 100644
index 037649312c..0000000000
--- a/system/linux_include/log/log.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/******************************************************************************
- *
- * Copyright 2018 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.
- *
- ******************************************************************************/
-#pragma once
-
-#ifndef __ANDROID__
-
-#include <cstdint>
-
-#endif
diff --git a/system/log/OWNERS b/system/log/OWNERS
deleted file mode 100644
index d1c75de900..0000000000
--- a/system/log/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-henrichataing@google.com
diff --git a/system/main/shim/acl.cc b/system/main/shim/acl.cc
index b2f0e23975..b01bd1f92d 100644
--- a/system/main/shim/acl.cc
+++ b/system/main/shim/acl.cc
@@ -969,11 +969,6 @@ struct shim::Acl::impl {
maximum_latency, minimum_remote_timeout, minimum_local_timeout);
}
- void LeSetDefaultSubrate(uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency,
- uint16_t cont_num, uint16_t sup_tout) {
- GetAclManager()->LeSetDefaultSubrate(subrate_min, subrate_max, max_latency, cont_num, sup_tout);
- }
-
void LeSubrateRequest(HciHandle handle, uint16_t subrate_min, uint16_t subrate_max,
uint16_t max_latency, uint16_t cont_num, uint16_t sup_tout) {
if (IsLeAcl(handle)) {
@@ -1573,12 +1568,6 @@ void shim::Acl::UpdateConnectionParameters(uint16_t handle, uint16_t conn_int_mi
conn_int_max, conn_latency, conn_timeout, min_ce_len, max_ce_len);
}
-void shim::Acl::LeSetDefaultSubrate(uint16_t subrate_min, uint16_t subrate_max,
- uint16_t max_latency, uint16_t cont_num, uint16_t sup_tout) {
- handler_->CallOn(pimpl_.get(), &Acl::impl::LeSetDefaultSubrate, subrate_min, subrate_max,
- max_latency, cont_num, sup_tout);
-}
-
void shim::Acl::LeSubrateRequest(uint16_t hci_handle, uint16_t subrate_min, uint16_t subrate_max,
uint16_t max_latency, uint16_t cont_num, uint16_t sup_tout) {
handler_->CallOn(pimpl_.get(), &Acl::impl::LeSubrateRequest, hci_handle, subrate_min, subrate_max,
diff --git a/system/main/shim/acl.h b/system/main/shim/acl.h
index bbe15d0acf..8253faf013 100644
--- a/system/main/shim/acl.h
+++ b/system/main/shim/acl.h
@@ -80,8 +80,6 @@ public:
void RemoveFromAddressResolution(const hci::AddressWithType& address_with_type);
void ClearAddressResolution();
- void LeSetDefaultSubrate(uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency,
- uint16_t cont_num, uint16_t sup_tout);
void LeSubrateRequest(uint16_t hci_handle, uint16_t subrate_min, uint16_t subrate_max,
uint16_t max_latency, uint16_t cont_num, uint16_t sup_tout);
diff --git a/system/main/shim/acl_api.cc b/system/main/shim/acl_api.cc
index 56e63e1977..0868f40f2c 100644
--- a/system/main/shim/acl_api.cc
+++ b/system/main/shim/acl_api.cc
@@ -166,12 +166,6 @@ void bluetooth::shim::ACL_ClearAddressResolution() {
void bluetooth::shim::ACL_ClearFilterAcceptList() {
Stack::GetInstance()->GetAcl()->ClearFilterAcceptList();
}
-void bluetooth::shim::ACL_LeSetDefaultSubrate(uint16_t subrate_min, uint16_t subrate_max,
- uint16_t max_latency, uint16_t cont_num,
- uint16_t sup_tout) {
- Stack::GetInstance()->GetAcl()->LeSetDefaultSubrate(subrate_min, subrate_max, max_latency,
- cont_num, sup_tout);
-}
void bluetooth::shim::ACL_LeSubrateRequest(uint16_t hci_handle, uint16_t subrate_min,
uint16_t subrate_max, uint16_t max_latency,
diff --git a/system/main/shim/acl_api.h b/system/main/shim/acl_api.h
index 6b28988ca6..b0bac16e02 100644
--- a/system/main/shim/acl_api.h
+++ b/system/main/shim/acl_api.h
@@ -49,8 +49,6 @@ void ACL_AddToAddressResolution(const tBLE_BD_ADDR& legacy_address_with_type,
void ACL_RemoveFromAddressResolution(const tBLE_BD_ADDR& legacy_address_with_type);
void ACL_ClearAddressResolution();
void ACL_ClearFilterAcceptList();
-void ACL_LeSetDefaultSubrate(uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency,
- uint16_t cont_num, uint16_t sup_tout);
void ACL_SendConnectionParameterUpdateRequest(uint16_t handle, uint16_t conn_int_min,
uint16_t conn_int_max, uint16_t conn_latency,
uint16_t conn_timeout, uint16_t min_ce_len,
diff --git a/system/main/shim/stack.cc b/system/main/shim/stack.cc
index bb8994aee0..027361875d 100644
--- a/system/main/shim/stack.cc
+++ b/system/main/shim/stack.cc
@@ -67,9 +67,9 @@ namespace shim {
struct Stack::impl {
Acl* acl_ = nullptr;
- metrics::CounterMetrics* counter_metrics_ = nullptr;
- storage::StorageModule* storage_ = nullptr;
- hal::SnoopLogger* snoop_logger_ = nullptr;
+ std::shared_ptr<metrics::CounterMetrics> counter_metrics_ = nullptr;
+ std::shared_ptr<storage::StorageModule> storage_ = nullptr;
+ std::shared_ptr<hal::SnoopLogger> snoop_logger_ = nullptr;
};
Stack::Stack() { pimpl_ = std::make_shared<Stack::impl>(); }
@@ -89,9 +89,16 @@ void Stack::StartEverything() {
stack_thread_ = new os::Thread("gd_stack_thread", os::Thread::Priority::REAL_TIME);
stack_handler_ = new os::Handler(stack_thread_);
- pimpl_->counter_metrics_ = new metrics::CounterMetrics(new Handler(stack_thread_));
- pimpl_->storage_ = new storage::StorageModule(new Handler(stack_thread_));
- pimpl_->snoop_logger_ = new hal::SnoopLogger(new Handler(stack_thread_));
+ if (com::android::bluetooth::flags::same_handler_for_all_modules()) {
+ pimpl_->counter_metrics_ = std::make_shared<metrics::CounterMetrics>(stack_handler_);
+ pimpl_->storage_ = std::make_shared<storage::StorageModule>(stack_handler_);
+ pimpl_->snoop_logger_ = std::make_shared<hal::SnoopLogger>(stack_handler_);
+ } else {
+ pimpl_->counter_metrics_ =
+ std::make_shared<metrics::CounterMetrics>(new Handler(stack_thread_));
+ pimpl_->storage_ = std::make_shared<storage::StorageModule>(new Handler(stack_thread_));
+ pimpl_->snoop_logger_ = std::make_shared<hal::SnoopLogger>(new Handler(stack_thread_));
+ }
#if TARGET_FLOSS
modules.add<sysprops::SyspropsModule>();
@@ -119,6 +126,7 @@ void Stack::StartEverything() {
}
is_running_ = true;
+ log::info("GD stack is running");
std::promise<void> promise;
auto future = promise.get_future();
@@ -168,12 +176,13 @@ void Stack::Stop() {
log::assert_that(is_running_, "Gd stack not running");
is_running_ = false;
+ log::info("GD stack is not running");
- if (!com::android::bluetooth::flags::same_handler_for_all_modules()) {
- // Clear the handler only if the flag is not defined, otherwise it will be cleared by the
- // registry
- stack_handler_->Clear();
+ stack_handler_->Clear();
+ if(com::android::bluetooth::flags::same_handler_for_all_modules()) {
+ stack_handler_->WaitUntilStopped(bluetooth::kHandlerStopTimeout);
}
+
WakelockManager::Get().Acquire();
std::promise<void> promise;
@@ -195,14 +204,7 @@ void Stack::Stop() {
delete management_handler_;
delete management_thread_;
- if (!com::android::bluetooth::flags::same_handler_for_all_modules()) {
- // delete the handler only if the flag is not defined, otherwise it will be deleted by the
- // registry
- delete stack_handler_;
- }
-
- // stack_handler_ is already deleted by the registry in handle_shut_down, just set it to nullptr
- // to avoid any potential use-after-free
+ delete stack_handler_;
stack_handler_ = nullptr;
stack_thread_->Stop();
@@ -227,19 +229,19 @@ Acl* Stack::GetAcl() const {
metrics::CounterMetrics* Stack::GetCounterMetrics() const {
std::lock_guard<std::recursive_mutex> lock(mutex_);
log::assert_that(is_running_, "assert failed: is_running_");
- return pimpl_->counter_metrics_;
+ return pimpl_->counter_metrics_.get();
}
storage::StorageModule* Stack::GetStorage() const {
std::lock_guard<std::recursive_mutex> lock(mutex_);
log::assert_that(is_running_, "assert failed: is_running_");
- return pimpl_->storage_;
+ return pimpl_->storage_.get();
}
hal::SnoopLogger* Stack::GetSnoopLogger() const {
std::lock_guard<std::recursive_mutex> lock(mutex_);
log::assert_that(is_running_, "assert failed: is_running_");
- return pimpl_->snoop_logger_;
+ return pimpl_->snoop_logger_.get();
}
os::Handler* Stack::GetHandler() {
@@ -275,9 +277,15 @@ void Stack::handle_start_up(ModuleList* modules, std::promise<void> promise) {
void Stack::handle_shut_down(std::promise<void> promise) {
registry_.StopAll();
+
pimpl_->snoop_logger_->Stop();
pimpl_->storage_->Stop();
pimpl_->counter_metrics_->Stop();
+
+ pimpl_->snoop_logger_.reset();
+ pimpl_->storage_.reset();
+ pimpl_->counter_metrics_.reset();
+
promise.set_value();
}
diff --git a/system/main/test/main_shim_test.cc b/system/main/test/main_shim_test.cc
index 2f4056a381..c66024cabb 100644
--- a/system/main/test/main_shim_test.cc
+++ b/system/main/test/main_shim_test.cc
@@ -332,8 +332,10 @@ protected:
thread_ = new os::Thread("acl_thread", os::Thread::Priority::NORMAL);
handler_ = new os::Handler(thread_);
- /* extern */ test::mock_controller_ = new bluetooth::hci::testing::MockControllerInterface();
- /* extern */ test::mock_acl_manager_ = new bluetooth::hci::testing::MockAclManager();
+ /* extern */ test::mock_controller_ =
+ std::make_unique<bluetooth::hci::testing::MockControllerInterface>();
+ /* extern */ test::mock_acl_manager_ =
+ std::make_unique<bluetooth::hci::testing::MockAclManager>();
/* extern */ test::mock_le_scanning_manager_ =
new bluetooth::hci::testing::MockLeScanningManager();
/* extern */ test::mock_le_advertising_manager_ =
@@ -342,10 +344,8 @@ protected:
new bluetooth::hci::testing::MockDistanceMeasurementManager();
}
void TearDown() override {
- delete test::mock_controller_;
- test::mock_controller_ = nullptr;
- delete test::mock_acl_manager_;
- test::mock_acl_manager_ = nullptr;
+ test::mock_controller_.reset();
+ test::mock_acl_manager_.release();
delete test::mock_le_advertising_manager_;
test::mock_le_advertising_manager_ = nullptr;
delete test::mock_le_scanning_manager_;
@@ -567,7 +567,6 @@ TEST_F(MainShimTest, DISABLED_BleScannerInterfaceImpl_OnScanResult) {
bluetooth::shim::get_ble_scanner_instance());
EXPECT_CALL(*hci::testing::mock_le_scanning_manager_, RegisterScanningCallback(_)).Times(1);
- ;
bluetooth::shim::init_scanning_manager();
TestScanningCallbacks cb;
diff --git a/system/osi/BUILD.gn b/system/osi/BUILD.gn
index 5bdf04c1e9..fa47062f52 100644
--- a/system/osi/BUILD.gn
+++ b/system/osi/BUILD.gn
@@ -43,7 +43,6 @@ static_library("osi") {
include_dirs = [
"//bt/system/",
- "//bt/system/linux_include",
"//bt/system/osi/include_internal",
"//bt/system/stack/include",
]
diff --git a/system/pdl/hci/hci_packets.pdl b/system/pdl/hci/hci_packets.pdl
index fcdd255b99..838b1fa586 100644
--- a/system/pdl/hci/hci_packets.pdl
+++ b/system/pdl/hci/hci_packets.pdl
@@ -4949,7 +4949,8 @@ struct CsOptionalNadmRandomCapability {
struct CsOptionalCsSyncPhysSupported {
le_2m_phy : 1,
- _reserved_ : 7,
+ le_2m_2bt_phy : 1,
+ _reserved_ : 6,
}
struct CsOptionalSubfeaturesSupported {
@@ -5151,6 +5152,7 @@ enum CsConfigRttType : 8 {
enum CsSyncPhy : 8 {
LE_1M_PHY = 0x01,
LE_2M_PHY = 0x02,
+ LE_2M_2BT_PHY = 0x03,
}
enum CsChannelSelectionType : 8 {
diff --git a/system/stack/Android.bp b/system/stack/Android.bp
index ebab1ff5f4..78af467a76 100644
--- a/system/stack/Android.bp
+++ b/system/stack/Android.bp
@@ -48,7 +48,6 @@ cc_library_static {
"hid",
"include",
"l2cap",
- "metrics",
"pan",
"sdp",
"smp",
@@ -183,7 +182,6 @@ cc_library_static {
"l2cap/l2c_main.cc",
"l2cap/l2c_utils.cc",
"l2cap/l2cap_api.cc",
- "metrics/stack_metrics_logging.cc",
"pan/pan_api.cc",
"pan/pan_main.cc",
"pan/pan_utils.cc",
@@ -374,9 +372,9 @@ cc_fuzz {
":TestFakeOsi",
":TestMockBtif",
":TestMockDevice",
+ ":TestMockMainShim",
":TestMockStackBtm",
":TestMockStackL2cap",
- ":TestMockStackMetrics",
"fuzzers/sdp_fuzzer.cc",
],
static_libs: [
@@ -414,6 +412,7 @@ cc_fuzz {
":TestMockBtif",
":TestMockDevice",
":TestMockMainShim",
+ ":TestMockMainShim",
":TestMockMainShimEntry",
":TestMockSrvcDis",
":TestMockStackAcl",
@@ -421,7 +420,6 @@ cc_fuzz {
":TestMockStackBtm",
":TestMockStackHcic",
":TestMockStackL2cap",
- ":TestMockStackMetrics",
":TestMockStackSdp",
"fuzzers/rfcomm_fuzzer.cc",
"rfcomm/*.cc",
@@ -465,6 +463,7 @@ cc_fuzz {
":TestMockBtif",
":TestMockDevice",
":TestMockMainShim",
+ ":TestMockMainShim",
":TestMockMainShimEntry",
":TestMockSrvcDis",
":TestMockStackAcl",
@@ -473,7 +472,6 @@ cc_fuzz {
":TestMockStackConnMgr",
":TestMockStackHcic",
":TestMockStackL2cap",
- ":TestMockStackMetrics",
":TestMockStackSdp",
"ais/*.cc",
"eatt/*.cc",
@@ -517,12 +515,12 @@ cc_fuzz {
":TestMockBtif",
":TestMockDevice",
":TestMockMainShim",
+ ":TestMockMainShim",
":TestMockMainShimEntry",
":TestMockStackAcl",
":TestMockStackBtm",
":TestMockStackHcic",
":TestMockStackL2cap",
- ":TestMockStackMetrics",
"fuzzers/smp_fuzzer.cc",
"smp/*.cc", // add other sources files (p256 related) under smp into this test
],
@@ -563,12 +561,12 @@ cc_fuzz {
":TestMockBtif",
":TestMockDevice",
":TestMockMainShim",
+ ":TestMockMainShim",
":TestMockMainShimEntry",
":TestMockStackAcl",
":TestMockStackBtm",
":TestMockStackHcic",
":TestMockStackL2cap",
- ":TestMockStackMetrics",
"bnep/*.cc",
"fuzzers/bnep_fuzzer.cc",
],
@@ -601,12 +599,12 @@ cc_fuzz {
":TestMockBtif",
":TestMockDevice",
":TestMockMainShim",
+ ":TestMockMainShim",
":TestMockMainShimEntry",
":TestMockStackAcl",
":TestMockStackBtm",
":TestMockStackHcic",
":TestMockStackL2cap",
- ":TestMockStackMetrics",
":TestMockStackSdp",
"avct/*.cc",
"avrc/*.cc",
@@ -648,11 +646,11 @@ cc_fuzz {
":TestMockBtif",
":TestMockDevice",
":TestMockMainShim",
+ ":TestMockMainShim",
":TestMockMainShimEntry",
":TestMockStackAcl",
":TestMockStackBtm",
":TestMockStackHcic",
- ":TestMockStackMetrics",
"fuzzers/l2cap_fuzzer.cc",
"l2cap/*.cc",
],
@@ -809,10 +807,10 @@ cc_test {
":TestCommonMockFunctions",
":TestMockHci",
":TestMockMainShim",
+ ":TestMockMainShim",
":TestMockMainShimEntry",
":TestMockStackBtm",
":TestMockStackL2capInterface",
- ":TestMockStackMetrics",
":TestMockStackRfcommMetrics",
"rfcomm/port_api.cc",
"rfcomm/port_rfc.cc",
@@ -903,12 +901,12 @@ cc_test {
":TestMockBtif",
":TestMockDevice",
":TestMockMainShim",
+ ":TestMockMainShim",
":TestMockMainShimEntry",
":TestMockStackAcl",
":TestMockStackBtm",
":TestMockStackHcic",
":TestMockStackL2cap",
- ":TestMockStackMetrics",
"smp/p_256_curvepara.cc",
"smp/p_256_ecc_pp.cc",
"smp/p_256_multprecision.cc",
@@ -1006,9 +1004,9 @@ cc_test {
":TestCommonMainHandler",
":TestCommonMockFunctions",
":TestMockMainShim",
+ ":TestMockMainShim",
":TestMockMainShimEntry",
":TestMockStackBtm",
- ":TestMockStackMetrics",
"connection_manager/connection_manager.cc",
"test/connection_manager_test.cc",
],
@@ -1419,10 +1417,10 @@ cc_test {
":TestMockBtif",
":TestMockDevice",
":TestMockMainShim",
+ ":TestMockMainShim",
":TestMockStackBtm",
":TestMockStackConnMgr",
":TestMockStackL2cap",
- ":TestMockStackMetrics",
"gatt/gatt_db.cc",
"gatt/gatt_sr_hash.cc",
"gatt/gatt_utils.cc",
@@ -1675,7 +1673,6 @@ cc_test {
"btm/hfp_msbc_decoder.cc",
"btm/hfp_msbc_encoder.cc",
"btm/security_event_parser.cc",
- "metrics/stack_metrics_logging.cc",
"test/btm/peer_packet_types_test.cc",
"test/btm/sco_hci_test.cc",
"test/btm/sco_pkt_status_test.cc",
@@ -1813,9 +1810,9 @@ cc_test {
],
srcs: [
":TestCommonMockFunctions",
+ ":TestMockMainShim",
":TestMockStackBtm",
":TestMockStackL2cap",
- ":TestMockStackMetrics",
":TestMockStackSdp",
"hid/hidd_api.cc",
"hid/hidd_conn.cc",
@@ -1887,12 +1884,12 @@ cc_test {
":TestMockBtif",
":TestMockHci",
":TestMockMainShim",
+ ":TestMockMainShim",
":TestMockMainShimEntry",
":TestMockStackAcl",
":TestMockStackBtm",
":TestMockStackHcic",
":TestMockStackL2cap",
- ":TestMockStackMetrics",
":TestMockStackSmp",
"btu/btu_hcif.cc",
"btu/main_thread.cc",
@@ -1964,12 +1961,12 @@ cc_test {
":TestMockBtif",
":TestMockHci",
":TestMockMainShim",
+ ":TestMockMainShim",
":TestMockMainShimEntry",
":TestMockSrvcDis",
":TestMockStackAcl",
":TestMockStackBtm",
":TestMockStackL2cap",
- ":TestMockStackMetrics",
":TestMockStackSdp",
":TestMockStackSmp",
"ais/ais_ble.cc",
@@ -2165,6 +2162,7 @@ cc_test {
":TestMockHci",
":TestMockLegacyHciInterface",
":TestMockMainShim",
+ ":TestMockMainShim",
":TestMockMainShimEntry",
":TestMockStackBtm",
":TestMockStackBtu",
@@ -2172,7 +2170,6 @@ cc_test {
":TestMockStackGatt",
":TestMockStackHcic",
":TestMockStackL2cap",
- ":TestMockStackMetrics",
":TestMockStackSdp",
":TestMockStackSmp",
"acl/*.cc",
@@ -2349,9 +2346,9 @@ cc_test {
":TestFakeOsi",
":TestMockBta",
":TestMockBtif",
+ ":TestMockMainShim",
":TestMockStackBtm",
":TestMockStackL2cap",
- ":TestMockStackMetrics",
"test/sdp/stack_sdp_api_test.cc",
"test/sdp/stack_sdp_db_test.cc",
"test/sdp/stack_sdp_parse_test.cc",
diff --git a/system/stack/BUILD.gn b/system/stack/BUILD.gn
index d078d1bc14..f06a098bd5 100644
--- a/system/stack/BUILD.gn
+++ b/system/stack/BUILD.gn
@@ -149,7 +149,6 @@ source_set("stack") {
"l2cap/l2c_main.cc",
"l2cap/l2c_utils.cc",
"l2cap/l2cap_api.cc",
- "metrics/stack_metrics_logging.cc",
"pan/pan_api.cc",
"pan/pan_main.cc",
"pan/pan_utils.cc",
@@ -210,7 +209,6 @@ source_set("stack") {
"//bt/system/ctrlr/include",
"//bt/system/gd",
"//bt/system/hcis",
- "//bt/system/linux_include",
"//bt/system/rpc/include",
"//bt/system/udrv/include",
"//bt/system/vnd/ble",
@@ -367,7 +365,6 @@ if (defined(use.android) && use.android) {
include_dirs = [
"//bt/system/",
- "//bt/system/linux_include",
"//bt/system/bta/include",
"//bt/system/bta/sys",
"//bt/system/embdrv/sbc/encoder/include",
diff --git a/system/stack/acl/btm_acl.cc b/system/stack/acl/btm_acl.cc
index 69afab3bfa..1a4c292d55 100644
--- a/system/stack/acl/btm_acl.cc
+++ b/system/stack/acl/btm_acl.cc
@@ -41,7 +41,6 @@
#include "bta/gatt/bta_gattc_int.h"
#include "bta/include/bta_dm_acl.h"
#include "bta/sys/bta_sys.h"
-#include "common/metrics.h"
#include "device/include/device_iot_config.h"
#include "device/include/interop.h"
#include "hci/controller_interface.h"
@@ -51,6 +50,7 @@
#include "main/shim/dumpsys.h"
#include "main/shim/entry.h"
#include "main/shim/helpers.h"
+#include "os/metrics.h"
#include "os/parameter_provider.h"
#include "osi/include/allocator.h"
#include "osi/include/properties.h"
@@ -785,10 +785,10 @@ static void btm_process_remote_version_complete(uint8_t status, uint16_t handle,
p_acl_cb->remote_version_info.valid = true;
BTM_update_version_info(p_acl_cb->RemoteAddress(), p_acl_cb->remote_version_info);
- bluetooth::common::LogRemoteVersionInfo(handle, status, lmp_version, manufacturer,
- lmp_subversion);
+ bluetooth::os::LogMetricRemoteVersionInfo(handle, status, lmp_version, manufacturer,
+ lmp_subversion);
} else {
- bluetooth::common::LogRemoteVersionInfo(handle, status, 0, 0, 0);
+ bluetooth::os::LogMetricRemoteVersionInfo(handle, status, 0, 0, 0);
}
}
diff --git a/system/stack/btm/btm_ble_sec.cc b/system/stack/btm/btm_ble_sec.cc
index b7db7fa130..679e937eef 100644
--- a/system/stack/btm/btm_ble_sec.cc
+++ b/system/stack/btm/btm_ble_sec.cc
@@ -1621,8 +1621,16 @@ void btm_ble_connection_established(const RawAddress& bda) {
!p_dev_rec->sec_rec.is_le_link_key_known())) {
// Unknown device
if (p_dev_rec->dev_class == kDevClassEmpty || p_dev_rec->dev_class == kDevClassUnclassified) {
- // Class of device not known, read appearance characteristic
- btm_ble_read_remote_cod(bda);
+ // Class of device not known, read appearance characteristic ...
+ // Unless it is one of those devices which don't respond to this request
+ BD_NAME remote_name = {};
+ if (p_dev_rec->sec_rec.is_name_known() && BTM_GetRemoteDeviceName(bda, remote_name) &&
+ interop_match_name(INTEROP_DISABLE_READ_LE_APPEARANCE, (const char*)remote_name)) {
+ log::warn("Name {} matches IOP database, not reading appearance for {}",
+ (const char*)remote_name, bda);
+ } else {
+ btm_ble_read_remote_cod(bda);
+ }
}
}
}
@@ -1654,6 +1662,13 @@ static bool btm_ble_complete_evt_ignore(const tBTM_SEC_DEV_REC* p_dev_rec,
p_dev_rec->bd_addr);
l2cu_start_post_bond_timer(p_dev_rec->ble_hci_handle);
return true;
+ } else if (com::android::bluetooth::flags::le_peripheral_enc_failure() &&
+ !p_dev_rec->role_central) {
+ log::warn("Peripheral encryption request failed for the bonded device {} with reason {}",
+ p_dev_rec->bd_addr, smp_status_text(p_data->complt.reason));
+ btm_sec_disconnect(p_dev_rec->ble_hci_handle, HCI_ERR_AUTH_FAILURE,
+ smp_status_text(p_data->complt.reason));
+ return true;
}
}
@@ -1694,6 +1709,11 @@ static void btm_ble_complete_evt(const RawAddress& bd_addr, tBTM_SEC_DEV_REC* p_
}
BTM_BLE_SEC_CALLBACK(BTM_LE_COMPLT_EVT, bd_addr, p_data);
+ p_dev_rec = btm_find_dev(bd_addr); // BTM_LE_COMPLT_EVT event may have removed the device
+ if (p_dev_rec == nullptr) {
+ log::warn("Device record removed {}", bd_addr);
+ return;
+ }
log::verbose("before update sec_level=0x{:x} sec_flags=0x{:x}", p_data->complt.sec_level,
p_dev_rec->sec_rec.sec_flags);
diff --git a/system/stack/btm/btm_dev.cc b/system/stack/btm/btm_dev.cc
index 92dc80e1ab..992a59236c 100644
--- a/system/stack/btm/btm_dev.cc
+++ b/system/stack/btm/btm_dev.cc
@@ -326,6 +326,10 @@ static bool is_handle_equal(void* data, void* context) {
*
******************************************************************************/
tBTM_SEC_DEV_REC* btm_find_dev_by_handle(uint16_t handle) {
+ if (handle == HCI_INVALID_HANDLE) {
+ return nullptr;
+ }
+
if (btm_sec_cb.sec_dev_rec == nullptr) {
return nullptr;
}
@@ -335,7 +339,7 @@ tBTM_SEC_DEV_REC* btm_find_dev_by_handle(uint16_t handle) {
return static_cast<tBTM_SEC_DEV_REC*>(list_node(n));
}
- return NULL;
+ return nullptr;
}
static bool is_not_same_identity_or_pseudo_address(void* data, void* context) {
diff --git a/system/stack/btm/btm_sco.cc b/system/stack/btm/btm_sco.cc
index c48b321448..82182135eb 100644
--- a/system/stack/btm/btm_sco.cc
+++ b/system/stack/btm/btm_sco.cc
@@ -44,6 +44,7 @@
#include "internal_include/bt_target.h"
#include "main/shim/entry.h"
#include "main/shim/helpers.h"
+#include "main/shim/metrics_api.h"
#include "osi/include/properties.h"
#include "osi/include/stack_power_telemetry.h"
#include "stack/btm/btm_int_types.h"
@@ -60,7 +61,6 @@
#include "stack/include/main_thread.h"
#include "stack/include/sco_hci_link_interface.h"
#include "stack/include/sdpdefs.h"
-#include "stack/include/stack_metrics_logging.h"
#include "types/raw_address.h"
extern tBTM_CB btm_cb;
@@ -1298,7 +1298,8 @@ static void btm_sco_on_disconnected(uint16_t hci_handle, tHCI_REASON reason) {
if (fill_plc_stats(&num_decoded_frames, &packet_loss_ratio)) {
const int16_t codec_id = sco_codec_type_to_id(codec_type);
const std::string codec = sco_codec_type_text(codec_type);
- log_hfp_audio_packet_loss_stats(bd_addr, num_decoded_frames, packet_loss_ratio, codec_id);
+ bluetooth::shim::LogMetricHfpPacketLossStats(bd_addr, num_decoded_frames, packet_loss_ratio,
+ codec_id);
log::debug(
"Stopped SCO codec:{}, num_decoded_frames:{}, "
"packet_loss_ratio:{:f}",
diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc
index b00b779eee..4595794cab 100644
--- a/system/stack/btm/btm_sec.cc
+++ b/system/stack/btm/btm_sec.cc
@@ -38,7 +38,6 @@
#include "bta/dm/bta_dm_act.h"
#include "bta/dm/bta_dm_sec_int.h"
#include "btif/include/btif_storage.h"
-#include "common/metrics.h"
#include "common/time_util.h"
#include "device/include/device_iot_config.h"
#include "device/include/interop.h"
@@ -47,7 +46,9 @@
#include "main/shim/acl_api.h"
#include "main/shim/entry.h"
#include "main/shim/helpers.h"
+#include "main/shim/metrics_api.h"
#include "metrics/bluetooth_event.h"
+#include "os/metrics.h"
#include "osi/include/allocator.h"
#include "osi/include/properties.h"
#include "stack/btm/btm_ble_int.h"
@@ -75,7 +76,6 @@
#include "stack/include/main_thread.h"
#include "stack/include/rnr_interface.h"
#include "stack/include/smp_api.h"
-#include "stack/include/stack_metrics_logging.h"
#include "types/bt_transport.h"
#include "types/raw_address.h"
@@ -1923,10 +1923,9 @@ static void btm_sec_bond_cancel_complete(void) {
void btm_create_conn_cancel_complete(uint8_t status, const RawAddress bd_addr) {
log::verbose("btm_create_conn_cancel_complete(): in State: {} status:{}",
tBTM_SEC_CB::btm_pair_state_descr(btm_sec_cb.pairing_state), status);
- log_link_layer_connection_event(
- &bd_addr, bluetooth::common::kUnknownConnectionHandle,
- android::bluetooth::DIRECTION_OUTGOING, android::bluetooth::LINK_TYPE_ACL,
- android::bluetooth::hci::CMD_CREATE_CONNECTION_CANCEL,
+ bluetooth::shim::LogMetricLinkLayerConnectionEvent(
+ &bd_addr, bluetooth::os::kUnknownConnectionHandle, android::bluetooth::DIRECTION_OUTGOING,
+ android::bluetooth::LINK_TYPE_ACL, android::bluetooth::hci::CMD_CREATE_CONNECTION_CANCEL,
android::bluetooth::hci::EVT_COMMAND_COMPLETE, android::bluetooth::hci::BLE_EVT_UNKNOWN,
status, android::bluetooth::hci::STATUS_UNKNOWN);
@@ -2440,8 +2439,7 @@ void btm_io_capabilities_req(RawAddress p) {
/* If device is bonded, and encrypted it's upgrading security and it's ok.
* If it's bonded and not encrypted, it's remote missing keys scenario */
- if (!p_dev_rec->sec_rec.is_device_encrypted() &&
- com::android::bluetooth::flags::key_missing_classic_device()) {
+ if (!p_dev_rec->sec_rec.is_device_encrypted()) {
log::warn("Incoming bond request, but {} is already bonded (notifying user)", p);
bta_dm_remote_key_missing(p);
btm_sec_disconnect(p_dev_rec->hci_handle, HCI_ERR_AUTH_FAILURE,
@@ -2632,8 +2630,7 @@ void btm_io_capabilities_rsp(const tBTM_SP_IO_RSP evt_data) {
/* If device is bonded, and encrypted it's upgrading security and it's ok.
* If it's bonded and not encrypted, it's remote missing keys scenario */
- if (btm_sec_is_a_bonded_dev(evt_data.bd_addr) && !p_dev_rec->sec_rec.is_device_encrypted() &&
- com::android::bluetooth::flags::key_missing_classic_device()) {
+ if (btm_sec_is_a_bonded_dev(evt_data.bd_addr) && !p_dev_rec->sec_rec.is_device_encrypted()) {
log::warn("Incoming bond request, but {} is already bonded (notifying user)", evt_data.bd_addr);
bta_dm_remote_key_missing(evt_data.bd_addr);
btm_sec_disconnect(p_dev_rec->hci_handle, HCI_ERR_AUTH_FAILURE,
@@ -3031,8 +3028,7 @@ void btm_sec_auth_complete(uint16_t handle, tHCI_STATUS status) {
p_dev_rec->sec_rec.classic_link, p_dev_rec->bd_addr,
reinterpret_cast<char const*>(p_dev_rec->sec_bd_name));
- if (status == HCI_ERR_KEY_MISSING &&
- com::android::bluetooth::flags::key_missing_classic_device()) {
+ if (status == HCI_ERR_KEY_MISSING) {
log::warn("auth_complete KEY_MISSING {} is already bonded (notifying user)",
p_dev_rec->bd_addr);
bta_dm_remote_key_missing(p_dev_rec->bd_addr);
@@ -3133,12 +3129,12 @@ void btm_sec_auth_complete(uint16_t handle, tHCI_STATUS status) {
p_dev_rec->sec_rec.security_required &= ~BTM_SEC_OUT_AUTHENTICATE;
if (status != HCI_SUCCESS) {
- if ((status != HCI_ERR_PEER_USER) && (status != HCI_ERR_CONN_CAUSE_LOCAL_HOST)) {
+ if (status != HCI_ERR_PEER_USER && status != HCI_ERR_CONN_CAUSE_LOCAL_HOST) {
btm_sec_send_hci_disconnect(
p_dev_rec, HCI_ERR_PEER_USER, p_dev_rec->hci_handle,
"stack::btm::btm_sec::btm_sec_auth_retry Auth fail while bonding");
}
- } else {
+ } else if (!com::android::bluetooth::flags::immediate_encryption_after_pairing()) {
BTM_LogHistory(kBtmLogTag, p_dev_rec->bd_addr, "Bonding completed",
hci_error_code_text(status));
@@ -3163,6 +3159,11 @@ void btm_sec_auth_complete(uint16_t handle, tHCI_STATUS status) {
}
l2cu_start_post_bond_timer(p_dev_rec->hci_handle);
+ } else {
+ BTM_LogHistory(kBtmLogTag, p_dev_rec->bd_addr, "Bonding completed",
+ hci_error_code_text(status));
+ BTM_SetEncryption(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR, NULL, NULL, BTM_BLE_SEC_NONE);
+ l2cu_start_post_bond_timer(p_dev_rec->hci_handle);
}
return;
@@ -3321,10 +3322,8 @@ void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, uint8_t encr_en
if (status == HCI_ERR_KEY_MISSING) {
log::info("Remote key missing - will report");
bta_dm_remote_key_missing(p_dev_rec->ble.pseudo_addr);
- if (com::android::bluetooth::flags::sec_disconnect_on_le_key_missing()) {
- btm_sec_send_hci_disconnect(p_dev_rec, HCI_ERR_HOST_REJECT_SECURITY,
- p_dev_rec->ble_hci_handle, "encryption_change:key_missing");
- }
+ btm_sec_send_hci_disconnect(p_dev_rec, HCI_ERR_HOST_REJECT_SECURITY,
+ p_dev_rec->ble_hci_handle, "encryption_change:key_missing");
return;
}
diff --git a/system/stack/btm/security_event_parser.cc b/system/stack/btm/security_event_parser.cc
index 84d7005d16..b107a69cb8 100644
--- a/system/stack/btm/security_event_parser.cc
+++ b/system/stack/btm/security_event_parser.cc
@@ -22,20 +22,19 @@
#include <string>
#include "btm_sec.h"
-#include "common/metrics.h"
#include "hci/hci_packets.h"
#include "main/shim/helpers.h"
+#include "main/shim/metrics_api.h"
+#include "os/metrics.h"
#include "stack/include/btm_sec_api_types.h"
#include "stack/include/hci_error_code.h"
#include "stack/include/sec_hci_link_interface.h"
-#include "stack/include/stack_metrics_logging.h"
#include "types/raw_address.h"
using namespace bluetooth;
using namespace bluetooth::hci;
using android::bluetooth::hci::CMD_UNKNOWN;
using android::bluetooth::hci::STATUS_UNKNOWN;
-using bluetooth::common::kUnknownConnectionHandle;
namespace bluetooth::stack::btm {
namespace {
@@ -44,19 +43,19 @@ static void log_address_and_status(const Address& bda, EventCode event_code,
uint32_t cmd = android::bluetooth::hci::CMD_UNKNOWN;
uint16_t status = static_cast<uint16_t>(event_status);
uint16_t reason = android::bluetooth::hci::STATUS_UNKNOWN;
- uint16_t handle = bluetooth::common::kUnknownConnectionHandle;
+ uint16_t handle = bluetooth::os::kUnknownConnectionHandle;
int64_t value = 0;
- log_classic_pairing_event(ToRawAddress(bda), handle, cmd, static_cast<uint16_t>(event_code),
- status, reason, value);
+ bluetooth::shim::LogMetricClassicPairingEvent(
+ ToRawAddress(bda), handle, cmd, static_cast<uint16_t>(event_code), status, reason, value);
}
static void log_address(const Address& bda, EventCode event_code) {
uint32_t cmd = android::bluetooth::hci::CMD_UNKNOWN;
uint16_t status = android::bluetooth::hci::STATUS_UNKNOWN;
uint16_t reason = android::bluetooth::hci::STATUS_UNKNOWN;
- uint16_t handle = bluetooth::common::kUnknownConnectionHandle;
+ uint16_t handle = bluetooth::os::kUnknownConnectionHandle;
int64_t value = 0;
- log_classic_pairing_event(ToRawAddress(bda), handle, cmd, static_cast<uint16_t>(event_code),
- status, reason, value);
+ bluetooth::shim::LogMetricClassicPairingEvent(
+ ToRawAddress(bda), handle, cmd, static_cast<uint16_t>(event_code), status, reason, value);
}
static void parse_encryption_change(const EventView event) {
auto change_opt = EncryptionChangeView::CreateOptional(event);
@@ -69,7 +68,7 @@ static void parse_encryption_change(const EventView event) {
btm_sec_encryption_change_evt(handle, static_cast<tHCI_STATUS>(status),
static_cast<uint8_t>(encr_enable), 0);
- log_classic_pairing_event(
+ bluetooth::shim::LogMetricClassicPairingEvent(
ToRawAddress(Address::kEmpty), handle, android::bluetooth::hci::CMD_UNKNOWN,
static_cast<uint32_t>(change.GetEventCode()), static_cast<uint16_t>(status),
android::bluetooth::hci::STATUS_UNKNOWN, 0);
@@ -86,7 +85,7 @@ static void parse_encryption_change_v2(const EventView event) {
btm_sec_encryption_change_evt(handle, static_cast<tHCI_STATUS>(status),
static_cast<uint8_t>(encr_enable), key_size);
- log_classic_pairing_event(
+ bluetooth::shim::LogMetricClassicPairingEvent(
ToRawAddress(Address::kEmpty), handle, android::bluetooth::hci::CMD_UNKNOWN,
static_cast<uint32_t>(change.GetEventCode()), static_cast<uint16_t>(status),
android::bluetooth::hci::STATUS_UNKNOWN, 0);
@@ -96,7 +95,7 @@ static void parse_change_connection_link_key_complete(const EventView event) {
log::assert_that(complete_opt.has_value(), "assert failed: complete_opt.has_value()");
auto complete = complete_opt.value();
- log_classic_pairing_event(
+ bluetooth::shim::LogMetricClassicPairingEvent(
ToRawAddress(Address::kEmpty), complete.GetConnectionHandle(),
android::bluetooth::hci::CMD_UNKNOWN, static_cast<uint32_t>(complete.GetEventCode()),
static_cast<uint16_t>(complete.GetStatus()), android::bluetooth::hci::STATUS_UNKNOWN, 0);
diff --git a/system/stack/btu/btu_hcif.cc b/system/stack/btu/btu_hcif.cc
index 7a4b6d1256..367c8a89c8 100644
--- a/system/stack/btu/btu_hcif.cc
+++ b/system/stack/btu/btu_hcif.cc
@@ -37,9 +37,10 @@
#include <cstdint>
#include "btm_iso_api.h"
-#include "common/metrics.h"
#include "internal_include/bt_target.h"
#include "main/shim/hci_layer.h"
+#include "main/shim/metrics_api.h"
+#include "os/metrics.h"
#include "osi/include/allocator.h"
#include "stack/include/acl_api.h"
#include "stack/include/acl_hci_link_interface.h"
@@ -59,7 +60,6 @@
#include "stack/include/sco_hci_link_interface.h"
#include "stack/include/sec_hci_link_interface.h"
#include "stack/include/smp_api.h"
-#include "stack/include/stack_metrics_logging.h"
#include "types/hci_role.h"
#include "types/raw_address.h"
@@ -110,7 +110,7 @@ static void btu_hcif_log_event_metrics(uint8_t evt_code, const uint8_t* p_event)
uint32_t cmd = android::bluetooth::hci::CMD_UNKNOWN;
uint16_t status = android::bluetooth::hci::STATUS_UNKNOWN;
uint16_t reason = android::bluetooth::hci::STATUS_UNKNOWN;
- uint16_t handle = bluetooth::common::kUnknownConnectionHandle;
+ uint16_t handle = bluetooth::os::kUnknownConnectionHandle;
int64_t value = 0;
RawAddress bda = RawAddress::kEmpty;
@@ -125,25 +125,29 @@ static void btu_hcif_log_event_metrics(uint8_t evt_code, const uint8_t* p_event)
case HCI_KEYPRESS_NOTIFY_EVT:
case HCI_REMOTE_OOB_DATA_REQUEST_EVT:
STREAM_TO_BDADDR(bda, p_event);
- log_classic_pairing_event(bda, handle, cmd, evt_code, status, reason, value);
+ bluetooth::shim::LogMetricClassicPairingEvent(bda, handle, cmd, evt_code, status, reason,
+ value);
break;
case HCI_SIMPLE_PAIRING_COMPLETE_EVT:
STREAM_TO_UINT8(status, p_event);
STREAM_TO_BDADDR(bda, p_event);
- log_classic_pairing_event(bda, handle, cmd, evt_code, status, reason, value);
+ bluetooth::shim::LogMetricClassicPairingEvent(bda, handle, cmd, evt_code, status, reason,
+ value);
break;
case HCI_AUTHENTICATION_COMP_EVT:
STREAM_TO_UINT8(status, p_event);
STREAM_TO_UINT16(handle, p_event);
handle = HCID_GET_HANDLE(handle);
- log_classic_pairing_event(bda, handle, cmd, evt_code, status, reason, value);
+ bluetooth::shim::LogMetricClassicPairingEvent(bda, handle, cmd, evt_code, status, reason,
+ value);
break;
case HCI_ENCRYPTION_CHANGE_EVT: {
uint8_t encryption_enabled;
STREAM_TO_UINT8(status, p_event);
STREAM_TO_UINT16(handle, p_event);
STREAM_TO_UINT8(encryption_enabled, p_event);
- log_classic_pairing_event(bda, handle, cmd, evt_code, status, reason, encryption_enabled);
+ bluetooth::shim::LogMetricClassicPairingEvent(bda, handle, cmd, evt_code, status, reason,
+ encryption_enabled);
break;
}
case HCI_ENCRYPTION_CHANGE_EVT_V2: {
@@ -153,7 +157,8 @@ static void btu_hcif_log_event_metrics(uint8_t evt_code, const uint8_t* p_event)
STREAM_TO_UINT16(handle, p_event);
STREAM_TO_UINT8(encryption_enabled, p_event);
STREAM_TO_UINT8(key_size, p_event);
- log_classic_pairing_event(bda, handle, cmd, evt_code, status, reason, encryption_enabled);
+ bluetooth::shim::LogMetricClassicPairingEvent(bda, handle, cmd, evt_code, status, reason,
+ encryption_enabled);
break;
}
case HCI_ESCO_CONNECTION_COMP_EVT: {
@@ -163,18 +168,19 @@ static void btu_hcif_log_event_metrics(uint8_t evt_code, const uint8_t* p_event)
STREAM_TO_BDADDR(bda, p_event);
STREAM_TO_UINT8(link_type, p_event);
handle = HCID_GET_HANDLE(handle);
- log_link_layer_connection_event(&bda, handle, android::bluetooth::DIRECTION_UNKNOWN,
- link_type, cmd, evt_code,
- android::bluetooth::hci::BLE_EVT_UNKNOWN, status, reason);
+ bluetooth::shim::LogMetricLinkLayerConnectionEvent(
+ &bda, handle, android::bluetooth::DIRECTION_UNKNOWN, link_type, cmd, evt_code,
+ android::bluetooth::hci::BLE_EVT_UNKNOWN, status, reason);
break;
}
case HCI_ESCO_CONNECTION_CHANGED_EVT: {
STREAM_TO_UINT8(status, p_event);
STREAM_TO_UINT16(handle, p_event);
handle = HCID_GET_HANDLE(handle);
- log_link_layer_connection_event(nullptr, handle, android::bluetooth::DIRECTION_UNKNOWN,
- android::bluetooth::LINK_TYPE_UNKNOWN, cmd, evt_code,
- android::bluetooth::hci::BLE_EVT_UNKNOWN, status, reason);
+ bluetooth::shim::LogMetricLinkLayerConnectionEvent(
+ nullptr, handle, android::bluetooth::DIRECTION_UNKNOWN,
+ android::bluetooth::LINK_TYPE_UNKNOWN, cmd, evt_code,
+ android::bluetooth::hci::BLE_EVT_UNKNOWN, status, reason);
break;
}
// Ignore these events
@@ -368,32 +374,33 @@ static void btu_hcif_log_command_metrics(uint16_t opcode, const uint8_t* p_cmd,
case HCI_CREATE_CONNECTION:
case HCI_CREATE_CONNECTION_CANCEL:
STREAM_TO_BDADDR(bd_addr, p_cmd);
- log_link_layer_connection_event(
- &bd_addr, bluetooth::common::kUnknownConnectionHandle,
+ bluetooth::shim::LogMetricLinkLayerConnectionEvent(
+ &bd_addr, bluetooth::os::kUnknownConnectionHandle,
android::bluetooth::DIRECTION_OUTGOING, android::bluetooth::LINK_TYPE_ACL, opcode,
hci_event, kUnknownBleEvt, cmd_status, android::bluetooth::hci::STATUS_UNKNOWN);
break;
case HCI_DISCONNECT:
STREAM_TO_UINT16(handle, p_cmd);
STREAM_TO_UINT8(reason, p_cmd);
- log_link_layer_connection_event(nullptr, handle, android::bluetooth::DIRECTION_UNKNOWN,
- android::bluetooth::LINK_TYPE_UNKNOWN, opcode, hci_event,
- kUnknownBleEvt, cmd_status, reason);
+ bluetooth::shim::LogMetricLinkLayerConnectionEvent(
+ nullptr, handle, android::bluetooth::DIRECTION_UNKNOWN,
+ android::bluetooth::LINK_TYPE_UNKNOWN, opcode, hci_event, kUnknownBleEvt, cmd_status,
+ reason);
break;
case HCI_SETUP_ESCO_CONNECTION:
case HCI_ENH_SETUP_ESCO_CONNECTION:
STREAM_TO_UINT16(handle, p_cmd);
- log_link_layer_connection_event(nullptr, handle, android::bluetooth::DIRECTION_OUTGOING,
- android::bluetooth::LINK_TYPE_UNKNOWN, opcode, hci_event,
- kUnknownBleEvt, cmd_status,
- android::bluetooth::hci::STATUS_UNKNOWN);
+ bluetooth::shim::LogMetricLinkLayerConnectionEvent(
+ nullptr, handle, android::bluetooth::DIRECTION_OUTGOING,
+ android::bluetooth::LINK_TYPE_UNKNOWN, opcode, hci_event, kUnknownBleEvt, cmd_status,
+ android::bluetooth::hci::STATUS_UNKNOWN);
break;
case HCI_ACCEPT_CONNECTION_REQUEST:
case HCI_ACCEPT_ESCO_CONNECTION:
case HCI_ENH_ACCEPT_ESCO_CONNECTION:
STREAM_TO_BDADDR(bd_addr, p_cmd);
- log_link_layer_connection_event(
- &bd_addr, bluetooth::common::kUnknownConnectionHandle,
+ bluetooth::shim::LogMetricLinkLayerConnectionEvent(
+ &bd_addr, bluetooth::os::kUnknownConnectionHandle,
android::bluetooth::DIRECTION_INCOMING, android::bluetooth::LINK_TYPE_UNKNOWN, opcode,
hci_event, kUnknownBleEvt, cmd_status, android::bluetooth::hci::STATUS_UNKNOWN);
break;
@@ -401,10 +408,10 @@ static void btu_hcif_log_command_metrics(uint16_t opcode, const uint8_t* p_cmd,
case HCI_REJECT_ESCO_CONNECTION:
STREAM_TO_BDADDR(bd_addr, p_cmd);
STREAM_TO_UINT8(reason, p_cmd);
- log_link_layer_connection_event(&bd_addr, bluetooth::common::kUnknownConnectionHandle,
- android::bluetooth::DIRECTION_INCOMING,
- android::bluetooth::LINK_TYPE_UNKNOWN, opcode, hci_event,
- kUnknownBleEvt, cmd_status, reason);
+ bluetooth::shim::LogMetricLinkLayerConnectionEvent(
+ &bd_addr, bluetooth::os::kUnknownConnectionHandle,
+ android::bluetooth::DIRECTION_INCOMING, android::bluetooth::LINK_TYPE_UNKNOWN, opcode,
+ hci_event, kUnknownBleEvt, cmd_status, reason);
break;
// BLE Commands
@@ -431,8 +438,8 @@ static void btu_hcif_log_command_metrics(uint16_t opcode, const uint8_t* p_cmd,
// Selectively log to avoid log spam due to acceptlist connections:
// - When doing non-acceptlist connection
// - When there is an error in command status
- log_link_layer_connection_event(
- bd_addr_p, bluetooth::common::kUnknownConnectionHandle,
+ bluetooth::shim::LogMetricLinkLayerConnectionEvent(
+ bd_addr_p, bluetooth::os::kUnknownConnectionHandle,
android::bluetooth::DIRECTION_OUTGOING, android::bluetooth::LINK_TYPE_ACL, opcode,
hci_event, kUnknownBleEvt, cmd_status, android::bluetooth::hci::STATUS_UNKNOWN);
}
@@ -456,8 +463,8 @@ static void btu_hcif_log_command_metrics(uint16_t opcode, const uint8_t* p_cmd,
// Selectively log to avoid log spam due to acceptlist connections:
// - When doing non-acceptlist connection
// - When there is an error in command status
- log_link_layer_connection_event(
- bd_addr_p, bluetooth::common::kUnknownConnectionHandle,
+ bluetooth::shim::LogMetricLinkLayerConnectionEvent(
+ bd_addr_p, bluetooth::os::kUnknownConnectionHandle,
android::bluetooth::DIRECTION_OUTGOING, android::bluetooth::LINK_TYPE_ACL, opcode,
hci_event, kUnknownBleEvt, cmd_status, android::bluetooth::hci::STATUS_UNKNOWN);
}
@@ -466,54 +473,56 @@ static void btu_hcif_log_command_metrics(uint16_t opcode, const uint8_t* p_cmd,
case HCI_BLE_CREATE_CONN_CANCEL:
if (cmd_status != HCI_SUCCESS && !is_cmd_status) {
// Only log errors to prevent log spam due to acceptlist connections
- log_link_layer_connection_event(
- nullptr, bluetooth::common::kUnknownConnectionHandle,
+ bluetooth::shim::LogMetricLinkLayerConnectionEvent(
+ nullptr, bluetooth::os::kUnknownConnectionHandle,
android::bluetooth::DIRECTION_OUTGOING, android::bluetooth::LINK_TYPE_ACL, opcode,
hci_event, kUnknownBleEvt, cmd_status, android::bluetooth::hci::STATUS_UNKNOWN);
}
break;
case HCI_READ_LOCAL_OOB_DATA:
case HCI_READ_LOCAL_OOB_EXTENDED_DATA:
- log_classic_pairing_event(RawAddress::kEmpty, bluetooth::common::kUnknownConnectionHandle,
- opcode, hci_event, cmd_status,
- android::bluetooth::hci::STATUS_UNKNOWN, 0);
+ bluetooth::shim::LogMetricClassicPairingEvent(
+ RawAddress::kEmpty, bluetooth::os::kUnknownConnectionHandle, opcode, hci_event,
+ cmd_status, android::bluetooth::hci::STATUS_UNKNOWN, 0);
break;
case HCI_WRITE_SIMPLE_PAIRING_MODE: {
uint8_t simple_pairing_mode;
STREAM_TO_UINT8(simple_pairing_mode, p_cmd);
- log_classic_pairing_event(RawAddress::kEmpty, bluetooth::common::kUnknownConnectionHandle,
- opcode, hci_event, cmd_status,
- android::bluetooth::hci::STATUS_UNKNOWN, simple_pairing_mode);
+ bluetooth::shim::LogMetricClassicPairingEvent(
+ RawAddress::kEmpty, bluetooth::os::kUnknownConnectionHandle, opcode, hci_event,
+ cmd_status, android::bluetooth::hci::STATUS_UNKNOWN, simple_pairing_mode);
break;
}
case HCI_WRITE_SECURE_CONNS_SUPPORT: {
uint8_t secure_conn_host_support;
STREAM_TO_UINT8(secure_conn_host_support, p_cmd);
- log_classic_pairing_event(RawAddress::kEmpty, bluetooth::common::kUnknownConnectionHandle,
- opcode, hci_event, cmd_status,
- android::bluetooth::hci::STATUS_UNKNOWN, secure_conn_host_support);
+ bluetooth::shim::LogMetricClassicPairingEvent(
+ RawAddress::kEmpty, bluetooth::os::kUnknownConnectionHandle, opcode, hci_event,
+ cmd_status, android::bluetooth::hci::STATUS_UNKNOWN, secure_conn_host_support);
break;
}
case HCI_AUTHENTICATION_REQUESTED:
STREAM_TO_UINT16(handle, p_cmd);
- log_classic_pairing_event(RawAddress::kEmpty, handle, opcode, hci_event, cmd_status,
- android::bluetooth::hci::STATUS_UNKNOWN, 0);
+ bluetooth::shim::LogMetricClassicPairingEvent(RawAddress::kEmpty, handle, opcode, hci_event,
+ cmd_status,
+ android::bluetooth::hci::STATUS_UNKNOWN, 0);
break;
case HCI_SET_CONN_ENCRYPTION: {
STREAM_TO_UINT16(handle, p_cmd);
uint8_t encryption_enable;
STREAM_TO_UINT8(encryption_enable, p_cmd);
- log_classic_pairing_event(RawAddress::kEmpty, handle, opcode, hci_event, cmd_status,
- android::bluetooth::hci::STATUS_UNKNOWN, encryption_enable);
+ bluetooth::shim::LogMetricClassicPairingEvent(
+ RawAddress::kEmpty, handle, opcode, hci_event, cmd_status,
+ android::bluetooth::hci::STATUS_UNKNOWN, encryption_enable);
break;
}
case HCI_DELETE_STORED_LINK_KEY: {
uint8_t delete_all_flag;
STREAM_TO_BDADDR(bd_addr, p_cmd);
STREAM_TO_UINT8(delete_all_flag, p_cmd);
- log_classic_pairing_event(bd_addr, bluetooth::common::kUnknownConnectionHandle, opcode,
- hci_event, cmd_status, android::bluetooth::hci::STATUS_UNKNOWN,
- delete_all_flag);
+ bluetooth::shim::LogMetricClassicPairingEvent(
+ bd_addr, bluetooth::os::kUnknownConnectionHandle, opcode, hci_event, cmd_status,
+ android::bluetooth::hci::STATUS_UNKNOWN, delete_all_flag);
break;
}
case HCI_RMT_NAME_REQUEST:
@@ -528,14 +537,16 @@ static void btu_hcif_log_command_metrics(uint16_t opcode, const uint8_t* p_cmd,
case HCI_REM_OOB_DATA_REQ_REPLY:
case HCI_REM_OOB_DATA_REQ_NEG_REPLY:
STREAM_TO_BDADDR(bd_addr, p_cmd);
- log_classic_pairing_event(bd_addr, bluetooth::common::kUnknownConnectionHandle, opcode,
- hci_event, cmd_status, android::bluetooth::hci::STATUS_UNKNOWN, 0);
+ bluetooth::shim::LogMetricClassicPairingEvent(
+ bd_addr, bluetooth::os::kUnknownConnectionHandle, opcode, hci_event, cmd_status,
+ android::bluetooth::hci::STATUS_UNKNOWN, 0);
break;
case HCI_IO_CAP_REQ_NEG_REPLY:
STREAM_TO_BDADDR(bd_addr, p_cmd);
STREAM_TO_UINT8(reason, p_cmd);
- log_classic_pairing_event(bd_addr, bluetooth::common::kUnknownConnectionHandle, opcode,
- hci_event, cmd_status, reason, 0);
+ bluetooth::shim::LogMetricClassicPairingEvent(bd_addr,
+ bluetooth::os::kUnknownConnectionHandle, opcode,
+ hci_event, cmd_status, reason, 0);
break;
}
}
@@ -599,8 +610,9 @@ static void btu_hcif_log_command_complete_metrics(uint16_t opcode, const uint8_t
case HCI_WRITE_SIMPLE_PAIRING_MODE:
case HCI_WRITE_SECURE_CONNS_SUPPORT:
STREAM_TO_UINT8(status, p_return_params);
- log_classic_pairing_event(RawAddress::kEmpty, bluetooth::common::kUnknownConnectionHandle,
- opcode, hci_event, status, reason, 0);
+ bluetooth::shim::LogMetricClassicPairingEvent(RawAddress::kEmpty,
+ bluetooth::os::kUnknownConnectionHandle, opcode,
+ hci_event, status, reason, 0);
break;
case HCI_READ_ENCR_KEY_SIZE: {
uint16_t handle;
@@ -608,8 +620,8 @@ static void btu_hcif_log_command_complete_metrics(uint16_t opcode, const uint8_t
STREAM_TO_UINT8(status, p_return_params);
STREAM_TO_UINT16(handle, p_return_params);
STREAM_TO_UINT8(key_size, p_return_params);
- log_classic_pairing_event(RawAddress::kEmpty, handle, opcode, hci_event, status, reason,
- key_size);
+ bluetooth::shim::LogMetricClassicPairingEvent(RawAddress::kEmpty, handle, opcode, hci_event,
+ status, reason, key_size);
break;
}
case HCI_LINK_KEY_REQUEST_REPLY:
@@ -624,8 +636,9 @@ static void btu_hcif_log_command_complete_metrics(uint16_t opcode, const uint8_t
case HCI_REM_OOB_DATA_REQ_NEG_REPLY:
STREAM_TO_UINT8(status, p_return_params);
STREAM_TO_BDADDR(bd_addr, p_return_params);
- log_classic_pairing_event(bd_addr, bluetooth::common::kUnknownConnectionHandle, opcode,
- hci_event, status, reason, 0);
+ bluetooth::shim::LogMetricClassicPairingEvent(bd_addr,
+ bluetooth::os::kUnknownConnectionHandle, opcode,
+ hci_event, status, reason, 0);
break;
}
}
diff --git a/system/stack/eatt/eatt_impl.h b/system/stack/eatt/eatt_impl.h
index 0d27726af4..b602636f0d 100644
--- a/system/stack/eatt/eatt_impl.h
+++ b/system/stack/eatt/eatt_impl.h
@@ -723,11 +723,7 @@ struct eatt_impl {
tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(channel->bda_, BT_TRANSPORT_LE);
log::warn("disconnecting channel {:#x} for {}", channel->cid_, channel->bda_);
- if (com::android::bluetooth::flags::gatt_disconnect_fix()) {
- EattExtension::GetInstance()->Disconnect(channel->bda_, channel->cid_);
- } else {
- gatt_disconnect(p_tcb);
- }
+ EattExtension::GetInstance()->Disconnect(channel->bda_, channel->cid_);
}
void start_indication_confirm_timer(const RawAddress& bd_addr, uint16_t cid) {
diff --git a/system/stack/fuzzers/l2cap_fuzzer.cc b/system/stack/fuzzers/l2cap_fuzzer.cc
index 6cb4d5170f..69243a67c4 100644
--- a/system/stack/fuzzers/l2cap_fuzzer.cc
+++ b/system/stack/fuzzers/l2cap_fuzzer.cc
@@ -121,26 +121,30 @@ public:
GetInterfaceToProfiles()->profileSpecific_HACK->GetHearingAidDeviceCount = []() { return 1; };
- ON_CALL(controller_, GetLeSuggestedDefaultDataLength).WillByDefault(Return(512));
+ bluetooth::hci::testing::mock_controller_ =
+ std::make_unique<bluetooth::hci::testing::MockControllerInterface>();
+ ON_CALL(*bluetooth::hci::testing::mock_controller_, GetLeSuggestedDefaultDataLength)
+ .WillByDefault(Return(512));
bluetooth::hci::LeBufferSize iso_size;
iso_size.le_data_packet_length_ = 512;
iso_size.total_num_le_packets_ = 6;
- ON_CALL(controller_, GetControllerIsoBufferSize).WillByDefault(Return(iso_size));
+ ON_CALL(*bluetooth::hci::testing::mock_controller_, GetControllerIsoBufferSize)
+ .WillByDefault(Return(iso_size));
bluetooth::hci::LeBufferSize le_size;
le_size.le_data_packet_length_ = 512;
le_size.total_num_le_packets_ = 6;
- ON_CALL(controller_, GetLeBufferSize).WillByDefault(Return(le_size));
- ON_CALL(controller_, SupportsBle).WillByDefault(Return(true));
- ON_CALL(controller_, GetAclPacketLength).WillByDefault(Return(512));
- bluetooth::hci::testing::mock_controller_ = &controller_;
+ ON_CALL(*bluetooth::hci::testing::mock_controller_, GetLeBufferSize)
+ .WillByDefault(Return(le_size));
+ ON_CALL(*bluetooth::hci::testing::mock_controller_, SupportsBle).WillByDefault(Return(true));
+ ON_CALL(*bluetooth::hci::testing::mock_controller_, GetAclPacketLength)
+ .WillByDefault(Return(512));
}
~FakeBtStack() {
test::mock::stack_acl::acl_send_data_packet_br_edr = {};
test::mock::stack_acl::acl_send_data_packet_ble = {};
- bluetooth::hci::testing::mock_controller_ = nullptr;
+ bluetooth::hci::testing::mock_controller_.reset();
}
- bluetooth::hci::testing::MockControllerInterface controller_;
};
class Fakes {
diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc
index 1b60132b00..bb5641d97d 100644
--- a/system/stack/gatt/gatt_api.cc
+++ b/system/stack/gatt/gatt_api.cc
@@ -34,6 +34,7 @@
#include "internal_include/bt_target.h"
#include "internal_include/stack_config.h"
#include "main/shim/helpers.h"
+#include "main/shim/metrics_api.h"
#include "os/system_properties.h"
#include "osi/include/allocator.h"
#include "stack/arbiter/acl_arbiter.h"
@@ -48,7 +49,6 @@
#include "stack/include/l2cap_interface.h"
#include "stack/include/l2cdefs.h"
#include "stack/include/sdp_api.h"
-#include "stack/include/stack_metrics_logging.h"
#include "types/bluetooth/uuid.h"
#include "types/bt_transport.h"
#include "types/raw_address.h"
@@ -75,8 +75,7 @@ static tGATT_HDL_LIST_ELEM& gatt_add_an_item_to_list(uint16_t s_handle) {
return *rit;
}
-static tGATT_IF GATT_Register_Dynamic(const Uuid& app_uuid128, const std::string& name,
- tGATT_CBACK* p_cb_info, bool eatt_support);
+static tGATT_IF GATT_FindNextFreeClRcbId();
/*****************************************************************************
*
@@ -1229,63 +1228,6 @@ void GATT_SetIdleTimeout(const RawAddress& bd_addr, uint16_t idle_tout, tBT_TRAN
******************************************************************************/
tGATT_IF GATT_Register(const Uuid& app_uuid128, const std::string& name, tGATT_CBACK* p_cb_info,
bool eatt_support) {
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- return GATT_Register_Dynamic(app_uuid128, name, p_cb_info, eatt_support);
- }
- tGATT_REG* p_reg;
- uint8_t i_gatt_if = 0;
- tGATT_IF gatt_if = 0;
-
- for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS; i_gatt_if++, p_reg++) {
- if (p_reg->in_use && p_reg->app_uuid128 == app_uuid128) {
- log::error("Application already registered, uuid={}", app_uuid128.ToString());
- return 0;
- }
- }
-
- if (stack_config_get_interface()->get_pts_use_eatt_for_all_services()) {
- log::info("PTS: Force to use EATT for servers");
- eatt_support = true;
- }
-
- for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS; i_gatt_if++, p_reg++) {
- if (!p_reg->in_use) {
- *p_reg = {};
- i_gatt_if++; /* one based number */
- p_reg->app_uuid128 = app_uuid128;
- gatt_if = p_reg->gatt_if = (tGATT_IF)i_gatt_if;
- p_reg->app_cb = *p_cb_info;
- p_reg->in_use = true;
- p_reg->eatt_support = eatt_support;
- p_reg->name = name;
- log::info("Allocated name:{} uuid:{} gatt_if:{} eatt_support:{}", name,
- app_uuid128.ToString(), gatt_if, eatt_support);
- return gatt_if;
- }
- }
-
- log::error("Unable to register GATT client, MAX client reached: {}", GATT_MAX_APPS);
- return 0;
-}
-
-static tGATT_IF GATT_FindNextFreeClRcbId() {
- tGATT_IF gatt_if = gatt_cb.last_gatt_if;
- for (int i = 0; i < GATT_IF_MAX; i++) {
- if (++gatt_if > GATT_IF_MAX) {
- gatt_if = static_cast<tGATT_IF>(1);
- }
- if (!gatt_cb.cl_rcb_map.contains(gatt_if)) {
- gatt_cb.last_gatt_if = gatt_if;
- return gatt_if;
- }
- }
- log::error("Unable to register GATT client, MAX client reached: {}", gatt_cb.cl_rcb_map.size());
-
- return GATT_IF_INVALID;
-}
-
-static tGATT_IF GATT_Register_Dynamic(const Uuid& app_uuid128, const std::string& name,
- tGATT_CBACK* p_cb_info, bool eatt_support) {
for (auto& [gatt_if, p_reg] : gatt_cb.cl_rcb_map) {
if (p_reg->app_uuid128 == app_uuid128) {
log::error("Application already registered, uuid={}", app_uuid128.ToString());
@@ -1322,6 +1264,22 @@ static tGATT_IF GATT_Register_Dynamic(const Uuid& app_uuid128, const std::string
return gatt_if;
}
+static tGATT_IF GATT_FindNextFreeClRcbId() {
+ tGATT_IF gatt_if = gatt_cb.last_gatt_if;
+ for (int i = 0; i < GATT_IF_MAX; i++) {
+ if (++gatt_if > GATT_IF_MAX) {
+ gatt_if = static_cast<tGATT_IF>(1);
+ }
+ if (!gatt_cb.cl_rcb_map.contains(gatt_if)) {
+ gatt_cb.last_gatt_if = gatt_if;
+ return gatt_if;
+ }
+ }
+ log::error("Unable to register GATT client, MAX client reached: {}", gatt_cb.cl_rcb_map.size());
+
+ return GATT_IF_INVALID;
+}
+
/*******************************************************************************
*
* Function GATT_Deregister
@@ -1385,11 +1343,7 @@ void GATT_Deregister(tGATT_IF gatt_if) {
connection_manager::on_app_deregistered(gatt_if);
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- gatt_cb.cl_rcb_map.erase(gatt_if);
- } else {
- *p_reg = {};
- }
+ gatt_cb.cl_rcb_map.erase(gatt_if);
}
/*******************************************************************************
@@ -1476,7 +1430,8 @@ bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBLE_ADDR_TYPE ad
return true;
}
- log_le_connection_lifecycle(ToGdAddress(bd_addr), true /* is_connect */, is_direct);
+ bluetooth::shim::LogMetricLeConnectionLifecycle(ToGdAddress(bd_addr), true /* is_connect */,
+ is_direct);
bool ret = false;
if (is_direct) {
@@ -1618,8 +1573,8 @@ tGATT_STATUS GATT_Disconnect(tCONN_ID conn_id) {
return GATT_ILLEGAL_PARAMETER;
}
- log_le_connection_lifecycle(ToGdAddress(p_tcb->peer_bda), true /* is_connect */,
- false /* is_direct */);
+ bluetooth::shim::LogMetricLeConnectionLifecycle(ToGdAddress(p_tcb->peer_bda),
+ true /* is_connect */, false /* is_direct */);
tGATT_IF gatt_if = gatt_get_gatt_if(conn_id);
gatt_update_app_use_link_flag(gatt_if, p_tcb, false, true);
diff --git a/system/stack/gatt/gatt_auth.cc b/system/stack/gatt/gatt_auth.cc
index 7c4b935389..34dcb4886b 100644
--- a/system/stack/gatt/gatt_auth.cc
+++ b/system/stack/gatt/gatt_auth.cc
@@ -23,7 +23,6 @@
******************************************************************************/
#include <bluetooth/log.h>
-#include <com_android_bluetooth_flags.h>
#include <string.h>
#include "gatt_api.h"
@@ -216,17 +215,9 @@ void gatt_notify_enc_cmpl(const RawAddress& bd_addr) {
return;
}
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& [i, p_rcb] : gatt_cb.cl_rcb_map) {
- if (p_rcb->app_cb.p_enc_cmpl_cb) {
- (*p_rcb->app_cb.p_enc_cmpl_cb)(p_rcb->gatt_if, bd_addr);
- }
- }
- } else {
- for (uint8_t i = 0; i < GATT_MAX_APPS; i++) {
- if (gatt_cb.cl_rcb[i].in_use && gatt_cb.cl_rcb[i].app_cb.p_enc_cmpl_cb) {
- (*gatt_cb.cl_rcb[i].app_cb.p_enc_cmpl_cb)(gatt_cb.cl_rcb[i].gatt_if, bd_addr);
- }
+ for (auto& [i, p_rcb] : gatt_cb.cl_rcb_map) {
+ if (p_rcb->app_cb.p_enc_cmpl_cb) {
+ (*p_rcb->app_cb.p_enc_cmpl_cb)(p_rcb->gatt_if, bd_addr);
}
}
diff --git a/system/stack/gatt/gatt_cl.cc b/system/stack/gatt/gatt_cl.cc
index 9a241813ae..8496d425a1 100644
--- a/system/stack/gatt/gatt_cl.cc
+++ b/system/stack/gatt/gatt_cl.cc
@@ -25,7 +25,6 @@
#define LOG_TAG "bluetooth"
#include <bluetooth/log.h>
-#include <com_android_bluetooth_flags.h>
#include <string.h>
#include "gatt_int.h"
@@ -708,17 +707,9 @@ static void gatt_process_notification(tGATT_TCB& tcb, uint16_t cid, uint8_t op_c
// notification/indication
// Note: need to do the indication count and start timer first then do
// callback
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
- if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) {
- tcb.ind_count++;
- }
- }
- } else {
- for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) {
- if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) {
- tcb.ind_count++;
- }
+ for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
+ if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) {
+ tcb.ind_count++;
}
}
@@ -738,19 +729,10 @@ static void gatt_process_notification(tGATT_TCB& tcb, uint16_t cid, uint8_t op_c
gatt_cl_complete.att_value = value;
gatt_cl_complete.cid = cid;
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
- if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) {
- conn_id = gatt_create_conn_id(tcb.tcb_idx, p_reg->gatt_if);
- (*p_reg->app_cb.p_cmpl_cb)(conn_id, event, encrypt_status, &gatt_cl_complete);
- }
- }
- } else {
- for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) {
- if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) {
- conn_id = gatt_create_conn_id(tcb.tcb_idx, p_reg->gatt_if);
- (*p_reg->app_cb.p_cmpl_cb)(conn_id, event, encrypt_status, &gatt_cl_complete);
- }
+ for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
+ if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) {
+ conn_id = gatt_create_conn_id(tcb.tcb_idx, p_reg->gatt_if);
+ (*p_reg->app_cb.p_cmpl_cb)(conn_id, event, encrypt_status, &gatt_cl_complete);
}
}
@@ -788,19 +770,10 @@ static void gatt_process_notification(tGATT_TCB& tcb, uint16_t cid, uint8_t op_c
gatt_cl_complete.att_value = value;
gatt_cl_complete.cid = cid;
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
- if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) {
- conn_id = gatt_create_conn_id(tcb.tcb_idx, p_reg->gatt_if);
- (*p_reg->app_cb.p_cmpl_cb)(conn_id, event, encrypt_status, &gatt_cl_complete);
- }
- }
- } else {
- for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) {
- if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) {
- conn_id = gatt_create_conn_id(tcb.tcb_idx, p_reg->gatt_if);
- (*p_reg->app_cb.p_cmpl_cb)(conn_id, event, encrypt_status, &gatt_cl_complete);
- }
+ for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
+ if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb) {
+ conn_id = gatt_create_conn_id(tcb.tcb_idx, p_reg->gatt_if);
+ (*p_reg->app_cb.p_cmpl_cb)(conn_id, event, encrypt_status, &gatt_cl_complete);
}
}
}
diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc
index 56d268422c..5228369a26 100644
--- a/system/stack/gatt/gatt_main.cc
+++ b/system/stack/gatt/gatt_main.cc
@@ -282,7 +282,7 @@ bool gatt_disconnect(tGATT_TCB* p_tcb) {
return true;
}
- if (com::android::bluetooth::flags::gatt_disconnect_fix() && p_tcb->eatt) {
+ if (p_tcb->eatt) {
/* ATT is fixed channel and it is expected to drop ACL.
* Make sure all EATT channels are disconnected before doing that.
*/
@@ -624,21 +624,10 @@ static void gatt_channel_congestion(tGATT_TCB* p_tcb, bool congested) {
gatt_cl_send_next_cmd_inq(*p_tcb);
}
/* notifying all applications for the connection up event */
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
- if (p_reg->in_use && p_reg->app_cb.p_congestion_cb) {
- conn_id = gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if);
- (*p_reg->app_cb.p_congestion_cb)(conn_id, congested);
- }
- }
- } else {
- for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) {
- if (p_reg->in_use) {
- if (p_reg->app_cb.p_congestion_cb) {
- conn_id = gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if);
- (*p_reg->app_cb.p_congestion_cb)(conn_id, congested);
- }
- }
+ for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
+ if (p_reg->in_use && p_reg->app_cb.p_congestion_cb) {
+ conn_id = gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if);
+ (*p_reg->app_cb.p_congestion_cb)(conn_id, congested);
}
}
}
@@ -658,20 +647,10 @@ void gatt_notify_phy_updated(tHCI_STATUS status, uint16_t handle, uint8_t tx_phy
// TODO: Clean up this status conversion.
tGATT_STATUS gatt_status = static_cast<tGATT_STATUS>(status);
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
- if (p_reg->in_use && p_reg->app_cb.p_phy_update_cb) {
- tCONN_ID conn_id = gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if);
- (*p_reg->app_cb.p_phy_update_cb)(p_reg->gatt_if, conn_id, tx_phy, rx_phy, gatt_status);
- }
- }
- } else {
- for (int i = 0; i < GATT_MAX_APPS; i++) {
- tGATT_REG* p_reg = &gatt_cb.cl_rcb[i];
- if (p_reg->in_use && p_reg->app_cb.p_phy_update_cb) {
- tCONN_ID conn_id = gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if);
- (*p_reg->app_cb.p_phy_update_cb)(p_reg->gatt_if, conn_id, tx_phy, rx_phy, gatt_status);
- }
+ for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
+ if (p_reg->in_use && p_reg->app_cb.p_phy_update_cb) {
+ tCONN_ID conn_id = gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if);
+ (*p_reg->app_cb.p_phy_update_cb)(p_reg->gatt_if, conn_id, tx_phy, rx_phy, gatt_status);
}
}
}
@@ -684,22 +663,11 @@ void gatt_notify_conn_update(const RawAddress& remote, uint16_t interval, uint16
return;
}
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
- if (p_reg->in_use && p_reg->app_cb.p_conn_update_cb) {
- tCONN_ID conn_id = gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if);
- (*p_reg->app_cb.p_conn_update_cb)(p_reg->gatt_if, conn_id, interval, latency, timeout,
- static_cast<tGATT_STATUS>(status));
- }
- }
- } else {
- for (int i = 0; i < GATT_MAX_APPS; i++) {
- tGATT_REG* p_reg = &gatt_cb.cl_rcb[i];
- if (p_reg->in_use && p_reg->app_cb.p_conn_update_cb) {
- tCONN_ID conn_id = gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if);
- (*p_reg->app_cb.p_conn_update_cb)(p_reg->gatt_if, conn_id, interval, latency, timeout,
- static_cast<tGATT_STATUS>(status));
- }
+ for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
+ if (p_reg->in_use && p_reg->app_cb.p_conn_update_cb) {
+ tCONN_ID conn_id = gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if);
+ (*p_reg->app_cb.p_conn_update_cb)(p_reg->gatt_if, conn_id, interval, latency, timeout,
+ static_cast<tGATT_STATUS>(status));
}
}
}
@@ -717,22 +685,11 @@ void gatt_notify_subrate_change(uint16_t handle, uint16_t subrate_factor, uint16
return;
}
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
- if (p_reg->in_use && p_reg->app_cb.p_subrate_chg_cb) {
- tCONN_ID conn_id = gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if);
- (*p_reg->app_cb.p_subrate_chg_cb)(p_reg->gatt_if, conn_id, subrate_factor, latency,
- cont_num, timeout, static_cast<tGATT_STATUS>(status));
- }
- }
- } else {
- for (int i = 0; i < GATT_MAX_APPS; i++) {
- tGATT_REG* p_reg = &gatt_cb.cl_rcb[i];
- if (p_reg->in_use && p_reg->app_cb.p_subrate_chg_cb) {
- tCONN_ID conn_id = gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if);
- (*p_reg->app_cb.p_subrate_chg_cb)(p_reg->gatt_if, conn_id, subrate_factor, latency,
- cont_num, timeout, static_cast<tGATT_STATUS>(status));
- }
+ for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
+ if (p_reg->in_use && p_reg->app_cb.p_subrate_chg_cb) {
+ tCONN_ID conn_id = gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if);
+ (*p_reg->app_cb.p_subrate_chg_cb)(p_reg->gatt_if, conn_id, subrate_factor, latency, cont_num,
+ timeout, static_cast<tGATT_STATUS>(status));
}
}
}
@@ -976,37 +933,19 @@ static void gatt_send_conn_cback(tGATT_TCB* p_tcb) {
/* notifying all applications for the connection up event */
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
- if (!p_reg->in_use) {
- continue;
- }
-
- if (apps.find(p_reg->gatt_if) != apps.end()) {
- gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, true, true);
- }
-
- if (p_reg->app_cb.p_conn_cb) {
- conn_id = gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if);
- (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, p_tcb->peer_bda, conn_id, kGattConnected,
- GATT_CONN_OK, p_tcb->transport);
- }
+ for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
+ if (!p_reg->in_use) {
+ continue;
}
- } else {
- for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) {
- if (!p_reg->in_use) {
- continue;
- }
- if (apps.find(p_reg->gatt_if) != apps.end()) {
- gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, true, true);
- }
+ if (apps.find(p_reg->gatt_if) != apps.end()) {
+ gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, true, true);
+ }
- if (p_reg->app_cb.p_conn_cb) {
- conn_id = gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if);
- (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, p_tcb->peer_bda, conn_id, kGattConnected,
- GATT_CONN_OK, p_tcb->transport);
- }
+ if (p_reg->app_cb.p_conn_cb) {
+ conn_id = gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if);
+ (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, p_tcb->peer_bda, conn_id, kGattConnected,
+ GATT_CONN_OK, p_tcb->transport);
}
}
diff --git a/system/stack/gatt/gatt_sr.cc b/system/stack/gatt/gatt_sr.cc
index 133080c1db..f23b8b5dc9 100644
--- a/system/stack/gatt/gatt_sr.cc
+++ b/system/stack/gatt/gatt_sr.cc
@@ -407,27 +407,14 @@ static void gatt_process_exec_write_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op
trans_id = gatt_sr_enqueue_cmd(tcb, cid, op_code, 0);
gatt_sr_copy_prep_cnt_to_cback_cnt(tcb);
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- auto prep_cnt_it = tcb.prep_cnt_map.begin();
- while (prep_cnt_it != tcb.prep_cnt_map.end()) {
- gatt_if = prep_cnt_it->first;
- conn_id = gatt_create_conn_id(tcb.tcb_idx, gatt_if);
- tGATTS_DATA gatts_data;
- gatts_data.exec_write = flag;
- gatt_sr_send_req_callback(conn_id, trans_id, GATTS_REQ_TYPE_WRITE_EXEC, &gatts_data);
- prep_cnt_it = tcb.prep_cnt_map.erase(prep_cnt_it);
- }
- } else {
- for (uint8_t i = 0; i < GATT_MAX_APPS; i++) {
- if (tcb.prep_cnt[i]) {
- gatt_if = (tGATT_IF)(i + 1);
- conn_id = gatt_create_conn_id(tcb.tcb_idx, gatt_if);
- tGATTS_DATA gatts_data;
- gatts_data.exec_write = flag;
- gatt_sr_send_req_callback(conn_id, trans_id, GATTS_REQ_TYPE_WRITE_EXEC, &gatts_data);
- tcb.prep_cnt[i] = 0;
- }
- }
+ auto prep_cnt_it = tcb.prep_cnt_map.begin();
+ while (prep_cnt_it != tcb.prep_cnt_map.end()) {
+ gatt_if = prep_cnt_it->first;
+ conn_id = gatt_create_conn_id(tcb.tcb_idx, gatt_if);
+ tGATTS_DATA gatts_data;
+ gatts_data.exec_write = flag;
+ gatt_sr_send_req_callback(conn_id, trans_id, GATTS_REQ_TYPE_WRITE_EXEC, &gatts_data);
+ prep_cnt_it = tcb.prep_cnt_map.erase(prep_cnt_it);
}
} else { /* nothing needs to be executed , send response now */
log::warn("gatt_process_exec_write_req: no prepare write pending");
@@ -911,19 +898,10 @@ static void gatts_process_mtu_req(tGATT_TCB& tcb, uint16_t cid, uint16_t len, ui
gatts_data.mtu = tcb.payload_size;
/* Notify all registered application with new MTU size. Use a transaction ID */
/* of 0, as no response is allowed from applications */
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
- if (p_reg->in_use) {
- tCONN_ID conn_id = gatt_create_conn_id(tcb.tcb_idx, p_reg->gatt_if);
- gatt_sr_send_req_callback(conn_id, 0, GATTS_REQ_TYPE_MTU, &gatts_data);
- }
- }
- } else {
- for (int i = 0; i < GATT_MAX_APPS; i++) {
- if (gatt_cb.cl_rcb[i].in_use) {
- tCONN_ID conn_id = gatt_create_conn_id(tcb.tcb_idx, gatt_cb.cl_rcb[i].gatt_if);
- gatt_sr_send_req_callback(conn_id, 0, GATTS_REQ_TYPE_MTU, &gatts_data);
- }
+ for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
+ if (p_reg->in_use) {
+ tCONN_ID conn_id = gatt_create_conn_id(tcb.tcb_idx, p_reg->gatt_if);
+ gatt_sr_send_req_callback(conn_id, 0, GATTS_REQ_TYPE_MTU, &gatts_data);
}
}
}
diff --git a/system/stack/gatt/gatt_utils.cc b/system/stack/gatt/gatt_utils.cc
index f401be9285..28590330c5 100644
--- a/system/stack/gatt/gatt_utils.cc
+++ b/system/stack/gatt/gatt_utils.cc
@@ -24,7 +24,6 @@
#define LOG_TAG "gatt_utils"
#include <bluetooth/log.h>
-#include <com_android_bluetooth_flags.h>
#include <cstdint>
#include <deque>
@@ -1043,21 +1042,12 @@ tGATT_REG* gatt_get_regcb(tGATT_IF gatt_if) {
uint8_t ii = (uint8_t)gatt_if;
tGATT_REG* p_reg = NULL;
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- auto it = gatt_cb.cl_rcb_map.find(gatt_if);
- if (it == gatt_cb.cl_rcb_map.end()) {
- log::warn("unknown gatt_if = {}", ii);
- return NULL;
- }
- p_reg = it->second.get();
- } else {
- // Index for cl_rcb is always 1 less than gatt_if.
- if (ii < 1 || ii > GATT_MAX_APPS) {
- log::warn("gatt_if out of range = {}", ii);
- return NULL;
- }
- p_reg = &gatt_cb.cl_rcb[ii - 1];
+ auto it = gatt_cb.cl_rcb_map.find(gatt_if);
+ if (it == gatt_cb.cl_rcb_map.end()) {
+ log::warn("unknown gatt_if = {}", ii);
+ return NULL;
}
+ p_reg = it->second.get();
if (!p_reg->in_use) {
log::warn("gatt_if found but not in use.");
@@ -1332,16 +1322,8 @@ tGATT_TCB* gatt_find_tcb_by_cid(uint16_t lcid) {
}
void gatt_sr_copy_prep_cnt_to_cback_cnt(tGATT_TCB& tcb) {
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& [i, cnt] : tcb.prep_cnt_map) {
- tcb.sr_cmd.cback_cnt_map[i] = 1;
- }
- } else {
- for (uint8_t i = 0; i < GATT_MAX_APPS; i++) {
- if (tcb.prep_cnt[i]) {
- tcb.sr_cmd.cback_cnt[i] = 1;
- }
- }
+ for (auto& [i, cnt] : tcb.prep_cnt_map) {
+ tcb.sr_cmd.cback_cnt_map[i] = 1;
}
}
@@ -1385,17 +1367,7 @@ bool gatt_sr_is_cback_cnt_zero(tGATT_TCB& tcb, uint16_t cid) {
sr_cmd_p = &channel->server_outstanding_cmd_;
}
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- return sr_cmd_p->cback_cnt_map.empty();
- }
-
- for (uint8_t i = 0; i < GATT_MAX_APPS; i++) {
- if (sr_cmd_p->cback_cnt[i] != 0) {
- return false;
- }
- }
-
- return true;
+ return sr_cmd_p->cback_cnt_map.empty();
}
/*******************************************************************************
@@ -1407,18 +1379,7 @@ bool gatt_sr_is_cback_cnt_zero(tGATT_TCB& tcb, uint16_t cid) {
* Returns True no prepare write request
*
******************************************************************************/
-bool gatt_sr_is_prep_cnt_zero(tGATT_TCB& tcb) {
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- return tcb.prep_cnt_map.empty();
- } else {
- for (uint8_t i = 0; i < GATT_MAX_APPS; i++) {
- if (tcb.prep_cnt[i]) {
- return false;
- }
- }
- return true;
- }
-}
+bool gatt_sr_is_prep_cnt_zero(tGATT_TCB& tcb) { return tcb.prep_cnt_map.empty(); }
/*******************************************************************************
*
@@ -1430,31 +1391,15 @@ bool gatt_sr_is_prep_cnt_zero(tGATT_TCB& tcb) {
*
******************************************************************************/
void gatt_sr_reset_cback_cnt(tGATT_TCB& tcb, uint16_t cid) {
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- if (cid == tcb.att_lcid) {
- tcb.sr_cmd.cback_cnt_map.clear();
- } else {
- EattChannel* channel = EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
- if (channel == nullptr) {
- log::warn("{}, cid 0x{:02x} already disconnected", tcb.peer_bda, cid);
- return;
- }
- channel->server_outstanding_cmd_.cback_cnt_map.clear();
- }
+ if (cid == tcb.att_lcid) {
+ tcb.sr_cmd.cback_cnt_map.clear();
} else {
- for (uint8_t i = 0; i < GATT_MAX_APPS; i++) {
- if (cid == tcb.att_lcid) {
- tcb.sr_cmd.cback_cnt[i] = 0;
- } else {
- EattChannel* channel =
- EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
- if (channel == nullptr) {
- log::warn("{}, cid 0x{:02x} already disconnected", tcb.peer_bda, cid);
- return;
- }
- channel->server_outstanding_cmd_.cback_cnt[i] = 0;
- }
+ EattChannel* channel = EattExtension::GetInstance()->FindEattChannelByCid(tcb.peer_bda, cid);
+ if (channel == nullptr) {
+ log::warn("{}, cid 0x{:02x} already disconnected", tcb.peer_bda, cid);
+ return;
}
+ channel->server_outstanding_cmd_.cback_cnt_map.clear();
}
}
@@ -1540,25 +1485,13 @@ void gatt_sr_update_cback_cnt(tGATT_TCB& tcb, uint16_t cid, tGATT_IF gatt_if, bo
gatt_sr_reset_cback_cnt(tcb, cid);
}
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- if (is_inc) {
- sr_cmd_p->cback_cnt_map[gatt_if]++;
- } else {
- auto cback_cnt_it = sr_cmd_p->cback_cnt_map.find(gatt_if);
- if (cback_cnt_it != sr_cmd_p->cback_cnt_map.end()) {
- if ((--cback_cnt_it->second) <= 0) {
- sr_cmd_p->cback_cnt_map.erase(cback_cnt_it);
- }
- }
- }
+ if (is_inc) {
+ sr_cmd_p->cback_cnt_map[gatt_if]++;
} else {
- uint8_t idx = ((uint8_t)gatt_if) - 1;
-
- if (is_inc) {
- sr_cmd_p->cback_cnt[idx]++;
- } else {
- if (sr_cmd_p->cback_cnt[idx]) {
- sr_cmd_p->cback_cnt[idx]--;
+ auto cback_cnt_it = sr_cmd_p->cback_cnt_map.find(gatt_if);
+ if (cback_cnt_it != sr_cmd_p->cback_cnt_map.end()) {
+ if ((--cback_cnt_it->second) <= 0) {
+ sr_cmd_p->cback_cnt_map.erase(cback_cnt_it);
}
}
}
@@ -1582,23 +1515,13 @@ void gatt_sr_update_prep_cnt(tGATT_TCB& tcb, tGATT_IF gatt_if, bool is_inc, bool
if (is_reset_first) {
gatt_sr_reset_prep_cnt(tcb);
}
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- if (is_inc) {
- tcb.prep_cnt_map[gatt_if]++;
- } else {
- auto prep_cnt_i = tcb.prep_cnt_map.find(gatt_if);
- if (prep_cnt_i != tcb.prep_cnt_map.end()) {
- if (--prep_cnt_i->second <= 0) {
- tcb.prep_cnt_map.erase(prep_cnt_i);
- }
- }
- }
+ if (is_inc) {
+ tcb.prep_cnt_map[gatt_if]++;
} else {
- if (is_inc) {
- tcb.prep_cnt[idx]++;
- } else {
- if (tcb.prep_cnt[idx]) {
- tcb.prep_cnt[idx]--;
+ auto prep_cnt_i = tcb.prep_cnt_map.find(gatt_if);
+ if (prep_cnt_i != tcb.prep_cnt_map.end()) {
+ if (--prep_cnt_i->second <= 0) {
+ tcb.prep_cnt_map.erase(prep_cnt_i);
}
}
}
@@ -1806,24 +1729,12 @@ static void gatt_disconnect_complete_notify_user(const RawAddress& bda, tGATT_DI
tBT_TRANSPORT transport) {
tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bda, transport);
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
- if (p_reg->in_use && p_reg->app_cb.p_conn_cb) {
- tCONN_ID conn_id =
- p_tcb ? gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if) : GATT_INVALID_CONN_ID;
- (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, bda, conn_id, kGattDisconnected, reason,
- transport);
- }
- }
- } else {
- for (uint8_t i = 0; i < GATT_MAX_APPS; i++) {
- tGATT_REG* p_reg = &gatt_cb.cl_rcb[i];
- if (p_reg->in_use && p_reg->app_cb.p_conn_cb) {
- tCONN_ID conn_id =
- p_tcb ? gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if) : GATT_INVALID_CONN_ID;
- (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, bda, conn_id, kGattDisconnected, reason,
- transport);
- }
+ for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
+ if (p_reg->in_use && p_reg->app_cb.p_conn_cb) {
+ tCONN_ID conn_id =
+ p_tcb ? gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if) : GATT_INVALID_CONN_ID;
+ (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, bda, conn_id, kGattDisconnected, reason,
+ transport);
}
}
}
@@ -1943,41 +1854,22 @@ uint16_t gatt_get_mtu_pref(const tGATT_REG* p_reg, const RawAddress& bda) {
uint16_t gatt_get_apps_preferred_mtu(const RawAddress& bda) {
uint16_t preferred_mtu = 0;
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
- if (!p_reg->in_use) {
- continue;
- }
-
- preferred_mtu = std::max(preferred_mtu, gatt_get_mtu_pref(p_reg.get(), bda));
+ for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
+ if (!p_reg->in_use) {
+ continue;
}
- } else {
- for (auto& reg : gatt_cb.cl_rcb) {
- if (!reg.in_use) {
- continue;
- }
- preferred_mtu = std::max(preferred_mtu, gatt_get_mtu_pref(&reg, bda));
- }
+ preferred_mtu = std::max(preferred_mtu, gatt_get_mtu_pref(p_reg.get(), bda));
}
return preferred_mtu;
}
void gatt_remove_apps_mtu_prefs(const RawAddress& bda) {
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
- if (!p_reg->in_use) {
- continue;
- }
- p_reg.get()->mtu_prefs.erase(bda);
- }
- } else {
- for (auto& reg : gatt_cb.cl_rcb) {
- if (!reg.in_use) {
- continue;
- }
- reg.mtu_prefs.erase(bda);
+ for (auto& [i, p_reg] : gatt_cb.cl_rcb_map) {
+ if (!p_reg->in_use) {
+ continue;
}
+ p_reg.get()->mtu_prefs.erase(bda);
}
}
diff --git a/system/stack/hid/hidd_api.cc b/system/stack/hid/hidd_api.cc
index 169868bbfc..58d9bdc07a 100644
--- a/system/stack/hid/hidd_api.cc
+++ b/system/stack/hid/hidd_api.cc
@@ -38,13 +38,13 @@
#include "hidd_int.h"
#include "hiddefs.h"
#include "internal_include/bt_target.h"
+#include "main/shim/metrics_api.h"
#include "osi/include/allocator.h"
#include "stack/include/bt_psm_types.h"
#include "stack/include/bt_types.h"
#include "stack/include/bt_uuid16.h"
#include "stack/include/sdp_api.h"
#include "stack/include/sdpdefs.h"
-#include "stack/include/stack_metrics_logging.h"
#include "stack/sdp/sdp_discovery_db.h"
#include "types/raw_address.h"
@@ -83,12 +83,14 @@ tHID_STATUS HID_DevRegister(tHID_DEV_HOST_CALLBACK* host_cback) {
log::verbose("");
if (hd_cb.reg_flag) {
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_ALREADY_REGISTERED, 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_ALREADY_REGISTERED, 1);
return HID_ERR_ALREADY_REGISTERED;
}
if (host_cback == NULL) {
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_HOST_CALLBACK_NULL, 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_HOST_CALLBACK_NULL, 1);
return HID_ERR_INVALID_PARAM;
}
@@ -122,7 +124,7 @@ tHID_STATUS HID_DevDeregister(void) {
log::verbose("");
if (!hd_cb.reg_flag) {
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_NOT_REGISTERED_AT_DEREGISTER, 1);
return HID_ERR_NOT_REGISTERED;
}
@@ -263,9 +265,10 @@ tHID_STATUS HID_DevAddRecord(uint32_t handle, char* p_name, char* p_description,
if (desc_len > HIDD_APP_DESCRIPTOR_LEN) {
log::error("descriptor length = {}, larger than max {}", desc_len, HIDD_APP_DESCRIPTOR_LEN);
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
- HIDD_ERR_NOT_REGISTERED_DUE_TO_DESCRIPTOR_LENGTH,
- 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::
+ HIDD_ERR_NOT_REGISTERED_DUE_TO_DESCRIPTOR_LENGTH,
+ 1);
return HID_ERR_NOT_REGISTERED;
};
@@ -273,9 +276,10 @@ tHID_STATUS HID_DevAddRecord(uint32_t handle, char* p_name, char* p_description,
if (p_buf == NULL) {
log::error("Buffer allocation failure for size = {}", buf_len);
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::
- HIDD_ERR_NOT_REGISTERED_DUE_TO_BUFFER_ALLOCATION,
- 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::
+ HIDD_ERR_NOT_REGISTERED_DUE_TO_BUFFER_ALLOCATION,
+ 1);
return HID_ERR_NOT_REGISTERED;
}
@@ -346,8 +350,8 @@ tHID_STATUS HID_DevAddRecord(uint32_t handle, char* p_name, char* p_description,
if (!result) {
log::error("failed to complete SDP record");
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_NOT_REGISTERED_AT_SDP,
- 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_NOT_REGISTERED_AT_SDP, 1);
return HID_ERR_NOT_REGISTERED;
}
@@ -376,7 +380,7 @@ tHID_STATUS HID_DevSendReport(uint8_t channel, uint8_t type, uint8_t id, uint16_
return hidd_conn_send_data(HID_CHANNEL_INTR, HID_TRANS_DATA, HID_PAR_REP_TYPE_INPUT, id, len,
p_data);
}
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_INVALID_PARAM_SEND_REPORT, 1);
return HID_ERR_INVALID_PARAM;
}
@@ -444,19 +448,20 @@ tHID_STATUS HID_DevUnplugDevice(const RawAddress& addr) {
******************************************************************************/
tHID_STATUS HID_DevConnect(void) {
if (!hd_cb.reg_flag) {
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_NOT_REGISTERED_AT_CONNECT, 1);
return HID_ERR_NOT_REGISTERED;
}
if (!hd_cb.device.in_use) {
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_DEVICE_NOT_IN_USE_AT_CONNECT, 1);
return HID_ERR_INVALID_PARAM;
}
if (hd_cb.device.state != HIDD_DEV_NO_CONN) {
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_ALREADY_CONN, 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_ALREADY_CONN, 1);
return HID_ERR_ALREADY_CONN;
}
@@ -474,13 +479,13 @@ tHID_STATUS HID_DevConnect(void) {
******************************************************************************/
tHID_STATUS HID_DevDisconnect(void) {
if (!hd_cb.reg_flag) {
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_NOT_REGISTERED_AT_DISCONNECT, 1);
return HID_ERR_NOT_REGISTERED;
}
if (!hd_cb.device.in_use) {
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_DEVICE_NOT_IN_USE_AT_DISCONNECT,
1);
return HID_ERR_INVALID_PARAM;
@@ -492,10 +497,11 @@ tHID_STATUS HID_DevDisconnect(void) {
tHID_STATUS ret = hidd_conn_disconnect();
hd_cb.device.conn.conn_state = HID_CONN_STATE_UNUSED;
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_ERR_DISCONNECTING, NULL);
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_DISCONNECTING, 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_DISCONNECTING, 1);
return ret;
}
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_NO_CONNECTION_AT_DISCONNECT, 1);
return HID_ERR_NO_CONNECTION;
}
@@ -565,7 +571,7 @@ tHID_STATUS HID_DevGetDevice(RawAddress* addr) {
if (hd_cb.device.in_use) {
*addr = hd_cb.device.addr;
} else {
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_NOT_REGISTERED_AT_GET_DEVICE, 1);
return HID_ERR_NOT_REGISTERED;
}
diff --git a/system/stack/hid/hidd_conn.cc b/system/stack/hid/hidd_conn.cc
index 7276af8acd..5f94c1c870 100644
--- a/system/stack/hid/hidd_conn.cc
+++ b/system/stack/hid/hidd_conn.cc
@@ -37,13 +37,13 @@
#include "hiddefs.h"
#include "internal_include/bt_target.h"
#include "l2cap_types.h"
+#include "main/shim/metrics_api.h"
#include "osi/include/allocator.h"
#include "stack/hid/hidd_int.h"
#include "stack/include/bt_hdr.h"
#include "stack/include/bt_psm_types.h"
#include "stack/include/l2cap_interface.h"
#include "stack/include/l2cdefs.h"
-#include "stack/include/stack_metrics_logging.h"
#include "types/bt_transport.h"
#include "types/raw_address.h"
@@ -300,7 +300,7 @@ static void hidd_l2cif_config_cfm(uint16_t cid, uint16_t /* initiator */, tL2CAP
log::warn("could not start L2CAP connection for INTR");
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_ERR_L2CAP_FAILED, NULL);
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_L2CAP_NOT_STARTED_INCOMING, 1);
return;
} else {
@@ -577,8 +577,8 @@ tHID_STATUS hidd_conn_reg(void) {
HID_PSM_CONTROL, dev_reg_info, false /* enable_snoop */, nullptr, HID_DEV_MTU_SIZE, 0,
BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)) {
log::error("HID Control (device) registration failed");
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_L2CAP_FAILED_CONTROL,
- 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_L2CAP_FAILED_CONTROL, 1);
return HID_ERR_L2CAP_FAILED;
}
@@ -587,8 +587,8 @@ tHID_STATUS hidd_conn_reg(void) {
0, BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)) {
stack::l2cap::get_interface().L2CA_Deregister(HID_PSM_CONTROL);
log::error("HID Interrupt (device) registration failed");
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_L2CAP_FAILED_INTERRUPT,
- 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_L2CAP_FAILED_INTERRUPT, 1);
return HID_ERR_L2CAP_FAILED;
}
@@ -627,14 +627,15 @@ tHID_STATUS hidd_conn_initiate(void) {
if (!p_dev->in_use) {
log::warn("no virtual cable established");
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_NOT_REGISTERED_AT_INITIATE, 1);
return HID_ERR_NOT_REGISTERED;
}
if (p_dev->conn.conn_state != HID_CONN_STATE_UNUSED) {
log::warn("connection already in progress");
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_CONN_IN_PROCESS, 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_CONN_IN_PROCESS, 1);
return HID_ERR_CONN_IN_PROCESS;
}
@@ -649,8 +650,8 @@ tHID_STATUS hidd_conn_initiate(void) {
HID_PSM_CONTROL, p_dev->addr, BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)) == 0) {
log::warn("could not start L2CAP connection");
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_ERR_L2CAP_FAILED, NULL);
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_L2CAP_FAILED_INITIATE,
- 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_L2CAP_FAILED_INITIATE, 1);
} else {
p_dev->conn.conn_state = HID_CONN_STATE_CONNECTING_CTRL;
}
@@ -723,7 +724,7 @@ tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type, uint8_t param
tHID_CONN* p_hcon = &hd_cb.device.conn;
if (p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED) {
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_CONGESTED_AT_FLAG_CHECK, 1);
return HID_ERR_CONGESTED;
}
@@ -744,13 +745,15 @@ tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type, uint8_t param
}
break;
default:
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_INVALID_PARAM, 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_INVALID_PARAM, 1);
return HID_ERR_INVALID_PARAM;
}
p_buf = (BT_HDR*)osi_malloc(buf_size);
if (p_buf == NULL) {
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_NO_RESOURCES, 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_NO_RESOURCES, 1);
return HID_ERR_NO_RESOURCES;
}
@@ -792,7 +795,7 @@ tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type, uint8_t param
return HID_SUCCESS;
}
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_NO_CONNECTION_AT_SEND_DATA, 1);
return HID_ERR_NO_CONNECTION;
}
@@ -800,7 +803,7 @@ tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type, uint8_t param
log::verbose("report sent");
if (stack::l2cap::get_interface().L2CA_DataWrite(cid, p_buf) == tL2CAP_DW_RESULT::FAILED) {
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDD_ERR_CONGESTED_AT_DATA_WRITE, 1);
return HID_ERR_CONGESTED;
}
diff --git a/system/stack/hid/hidh_api.cc b/system/stack/hid/hidh_api.cc
index 97d811ed5b..1ab5ba2a6a 100644
--- a/system/stack/hid/hidh_api.cc
+++ b/system/stack/hid/hidh_api.cc
@@ -37,6 +37,7 @@
#include "hiddefs.h"
#include "hidh_int.h"
#include "internal_include/bt_target.h"
+#include "main/shim/metrics_api.h"
#include "osi/include/alarm.h"
#include "osi/include/allocator.h"
#include "sdp_api.h"
@@ -44,7 +45,6 @@
#include "stack/include/bt_hdr.h"
#include "stack/include/bt_uuid16.h"
#include "stack/include/sdpdefs.h"
-#include "stack/include/stack_metrics_logging.h"
#include "stack/sdp/sdp_discovery_db.h"
#include "types/bluetooth/uuid.h"
#include "types/raw_address.h"
@@ -69,7 +69,8 @@ static void hidh_search_callback(const RawAddress& bd_addr, tSDP_RESULT sdp_resu
tHID_STATUS HID_HostGetSDPRecord(const RawAddress& addr, tSDP_DISCOVERY_DB* p_db, uint32_t db_len,
tHID_HOST_SDP_CALLBACK* sdp_cback) {
if (hh_cb.sdp_busy) {
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_SDP_BUSY, 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_SDP_BUSY, 1);
return HID_ERR_SDP_BUSY;
}
@@ -87,7 +88,8 @@ tHID_STATUS HID_HostGetSDPRecord(const RawAddress& addr, tSDP_DISCOVERY_DB* p_db
return HID_SUCCESS;
} else {
log::warn("Unable to start SDP service search request peer:{}", addr);
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_NO_RESOURCES_SDP, 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_NO_RESOURCES_SDP, 1);
return HID_ERR_NO_RESOURCES;
}
}
@@ -289,12 +291,13 @@ tHID_STATUS HID_HostRegister(tHID_HOST_DEV_CALLBACK* dev_cback) {
tHID_STATUS st;
if (hh_cb.reg_flag) {
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_ALREADY_REGISTERED, 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_ALREADY_REGISTERED, 1);
return HID_ERR_ALREADY_REGISTERED;
}
if (dev_cback == NULL) {
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_INVALID_PARAM_AT_HOST_REGISTER, 1);
return HID_ERR_INVALID_PARAM;
}
@@ -392,7 +395,7 @@ tHID_STATUS HID_HostAddDev(const RawAddress& addr, uint16_t attr_mask, uint8_t*
}
if (i == HID_HOST_MAX_DEVICES) {
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_NO_RESOURCES_ADD_DEVICE, 1);
return HID_ERR_NO_RESOURCES;
}
@@ -427,7 +430,7 @@ tHID_STATUS HID_HostRemoveDev(uint8_t dev_handle) {
}
if ((dev_handle >= HID_HOST_MAX_DEVICES) || (!hh_cb.devices[dev_handle].in_use)) {
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_INVALID_PARAM_AT_HOST_REMOVE_DEV,
1);
return HID_ERR_INVALID_PARAM;
@@ -457,13 +460,14 @@ tHID_STATUS HID_HostOpenDev(uint8_t dev_handle) {
}
if ((dev_handle >= HID_HOST_MAX_DEVICES) || (!hh_cb.devices[dev_handle].in_use)) {
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_INVALID_PARAM_AT_HOST_OPEN_DEV, 1);
return HID_ERR_INVALID_PARAM;
}
if (hh_cb.devices[dev_handle].state != HID_DEV_NO_CONN) {
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_ALREADY_CONN, 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_ALREADY_CONN, 1);
return HID_ERR_ALREADY_CONN;
}
@@ -494,13 +498,13 @@ tHID_STATUS HID_HostWriteDev(uint8_t dev_handle, uint8_t t_type, uint8_t param,
if ((dev_handle >= HID_HOST_MAX_DEVICES) || (!hh_cb.devices[dev_handle].in_use)) {
log::error("HID_ERR_INVALID_PARAM");
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_INVALID_PARAM_AT_HOST_WRITE_DEV,
1);
status = HID_ERR_INVALID_PARAM;
} else if (hh_cb.devices[dev_handle].state != HID_DEV_CONNECTED) {
log::error("HID_ERR_NO_CONNECTION dev_handle {}", dev_handle);
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_NO_CONNECTION_AT_HOST_WRITE_DEV,
1);
status = HID_ERR_NO_CONNECTION;
@@ -530,14 +534,14 @@ tHID_STATUS HID_HostCloseDev(uint8_t dev_handle) {
}
if ((dev_handle >= HID_HOST_MAX_DEVICES) || (!hh_cb.devices[dev_handle].in_use)) {
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_INVALID_PARAM_AT_HOST_CLOSE_DEV,
1);
return HID_ERR_INVALID_PARAM;
}
if (hh_cb.devices[dev_handle].state != HID_DEV_CONNECTED) {
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_NO_CONNECTION_AT_HOST_CLOSE_DEV,
1);
return HID_ERR_NO_CONNECTION;
diff --git a/system/stack/hid/hidh_conn.cc b/system/stack/hid/hidh_conn.cc
index cdc7906d16..71785478a1 100644
--- a/system/stack/hid/hidh_conn.cc
+++ b/system/stack/hid/hidh_conn.cc
@@ -39,6 +39,7 @@
#include "internal_include/bt_target.h"
#include "l2cap_types.h"
#include "l2cdefs.h"
+#include "main/shim/metrics_api.h"
#include "osi/include/alarm.h"
#include "osi/include/allocator.h"
#include "osi/include/osi.h"
@@ -48,7 +49,6 @@
#include "stack/include/btm_client_interface.h"
#include "stack/include/btm_log_history.h"
#include "stack/include/l2cap_interface.h"
-#include "stack/include/stack_metrics_logging.h"
#include "types/bt_transport.h"
#include "types/raw_address.h"
@@ -119,7 +119,7 @@ tHID_STATUS hidh_conn_reg(void) {
HID_PSM_CONTROL, hst_reg_info, false /* enable_snoop */, nullptr, HID_HOST_MTU, 0,
BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)) {
log::error("HID-Host Control Registration failed");
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_L2CAP_FAILED_AT_REGISTER_CONTROL,
1);
return HID_ERR_L2CAP_FAILED;
@@ -129,7 +129,7 @@ tHID_STATUS hidh_conn_reg(void) {
BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)) {
stack::l2cap::get_interface().L2CA_Deregister(HID_PSM_CONTROL);
log::error("HID-Host Interrupt Registration failed");
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_L2CAP_FAILED_AT_REGISTER_INTERRUPT,
1);
return HID_ERR_L2CAP_FAILED;
@@ -549,7 +549,8 @@ static void hidh_l2cif_disconnect_ind(uint16_t l2cap_cid, bool ack_needed) {
(disc_res == HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED) ||
(disc_res == HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE) ||
(disc_res == HCI_ERR_REPEATED_ATTEMPTS)) {
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_AUTH_FAILED, 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_AUTH_FAILED, 1);
hid_close_evt_reason = HID_ERR_AUTH_FAILED;
}
@@ -771,14 +772,14 @@ tHID_STATUS hidh_conn_snd_data(uint8_t dhandle, uint8_t trans_type, uint8_t para
if (!get_btm_client_interface().peer.BTM_IsAclConnectionUp(hh_cb.devices[dhandle].addr,
BT_TRANSPORT_BR_EDR)) {
osi_free(buf);
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_NO_CONNECTION_AT_SEND_DATA, 1);
return HID_ERR_NO_CONNECTION;
}
if (p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED) {
osi_free(buf);
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_CONGESTED_AT_FLAG_CHECK, 1);
return HID_ERR_CONGESTED;
}
@@ -799,7 +800,7 @@ tHID_STATUS hidh_conn_snd_data(uint8_t dhandle, uint8_t trans_type, uint8_t para
buf_size = HID_INTERRUPT_BUF_SIZE;
break;
default:
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_INVALID_PARAM_AT_SEND_DATA, 1);
return HID_ERR_INVALID_PARAM;
}
@@ -860,7 +861,7 @@ tHID_STATUS hidh_conn_snd_data(uint8_t dhandle, uint8_t trans_type, uint8_t para
/* Send the buffer through L2CAP */
if ((p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED) ||
(stack::l2cap::get_interface().L2CA_DataWrite(cid, p_buf) == tL2CAP_DW_RESULT::FAILED)) {
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_CONGESTED_AT_SEND_DATA, 1);
return HID_ERR_CONGESTED;
}
@@ -889,7 +890,8 @@ tHID_STATUS hidh_conn_initiate(uint8_t dhandle) {
tHID_HOST_DEV_CTB* p_dev = &hh_cb.devices[dhandle];
if (p_dev->conn.conn_state != HID_CONN_STATE_UNUSED) {
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_CONN_IN_PROCESS, 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_CONN_IN_PROCESS, 1);
return HID_ERR_CONN_IN_PROCESS;
}
@@ -908,7 +910,7 @@ tHID_STATUS hidh_conn_initiate(uint8_t dhandle) {
log::warn("HID-Host Originate failed");
hh_cb.callback(dhandle, hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, HID_ERR_L2CAP_FAILED,
NULL);
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::HIDH_ERR_L2CAP_FAILED_AT_INITIATE, 1);
} else {
/* Transition to the next appropriate state, waiting for connection confirm
diff --git a/system/stack/include/l2cap_interface.h b/system/stack/include/l2cap_interface.h
index b1551d2a80..19f85d4d2e 100644
--- a/system/stack/include/l2cap_interface.h
+++ b/system/stack/include/l2cap_interface.h
@@ -871,21 +871,6 @@ public:
virtual void L2CA_SetEcosystemBaseInterval(uint32_t base_interval) = 0;
/*******************************************************************************
- *
- * Function L2CA_SetDefaultSubrate
- *
- * Description BLE Set Default Subrate.
- *
- * Parameters: Subrate parameters
- *
- * Return value: void
- *
- ******************************************************************************/
- virtual void L2CA_SetDefaultSubrate(uint16_t subrate_min, uint16_t subrate_max,
- uint16_t max_latency, uint16_t cont_num,
- uint16_t timeout) = 0;
-
- /*******************************************************************************
**
** Function L2CA_SetMediaStreamChannel
**
diff --git a/system/stack/include/stack_metrics_logging.h b/system/stack/include/stack_metrics_logging.h
deleted file mode 100644
index 9a0a80baa4..0000000000
--- a/system/stack/include/stack_metrics_logging.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2021 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.
- */
-
-#pragma once
-
-#include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
-#include <frameworks/proto_logging/stats/enums/bluetooth/hci/enums.pb.h>
-
-#include <cstdint>
-
-#include "hci/address.h"
-#include "hci/hci_packets.h"
-#include "types/raw_address.h"
-
-void log_classic_pairing_event(const RawAddress& address, uint16_t handle, uint32_t hci_cmd,
- uint16_t hci_event, uint16_t cmd_status, uint16_t reason_code,
- int64_t event_value);
-
-void log_link_layer_connection_event(const RawAddress* address, uint32_t connection_handle,
- android::bluetooth::DirectionEnum direction,
- uint16_t link_type, uint32_t hci_cmd, uint16_t hci_event,
- uint16_t hci_ble_event, uint16_t cmd_status,
- uint16_t reason_code);
-
-void log_smp_pairing_event(const RawAddress& address, uint16_t smp_cmd,
- android::bluetooth::DirectionEnum direction, uint16_t smp_fail_reason);
-
-void log_sdp_attribute(const RawAddress& address, uint16_t protocol_uuid, uint16_t attribute_id,
- size_t attribute_size, const char* attribute_value);
-
-void log_manufacturer_info(const RawAddress& address,
- android::bluetooth::AddressTypeEnum address_type,
- android::bluetooth::DeviceInfoSrcEnum source_type,
- const std::string& source_name, const std::string& manufacturer,
- const std::string& model, const std::string& hardware_version,
- const std::string& software_version);
-
-void log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum key, int64_t value);
-
-void log_hfp_audio_packet_loss_stats(const RawAddress& address, int num_decoded_frames,
- double packet_loss_ratio, uint16_t codec_type);
-
-void log_mmc_transcode_rtt_stats(int maximum_rtt, double mean_rtt, int num_requests,
- int codec_type);
-
-void log_le_pairing_fail(const RawAddress& raw_address, uint8_t failure_reason, bool is_outgoing);
-
-void log_le_connection_status(bluetooth::hci::Address address, bool is_connect,
- bluetooth::hci::ErrorCode reason);
-
-void log_le_device_in_accept_list(bluetooth::hci::Address address, bool is_add);
-
-void log_le_connection_lifecycle(bluetooth::hci::Address address, bool is_connect, bool is_direct);
-
-void log_le_connection_completion(bluetooth::hci::Address address, bluetooth::hci::ErrorCode reason,
- bool is_locally_initiated);
diff --git a/system/stack/l2cap/internal/l2c_api.h b/system/stack/l2cap/internal/l2c_api.h
index dd1dbf52e6..989eccf50e 100644
--- a/system/stack/l2cap/internal/l2c_api.h
+++ b/system/stack/l2cap/internal/l2c_api.h
@@ -719,20 +719,6 @@ void L2CA_SetEcosystemBaseInterval(uint32_t base_interval);
/*******************************************************************************
*
- * Function L2CA_SetDefaultSubrate
- *
- * Description BLE Set Default Subrate.
- *
- * Parameters: Subrate parameters
- *
- * Return value: void
- *
- ******************************************************************************/
-void L2CA_SetDefaultSubrate(uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency,
- uint16_t cont_num, uint16_t timeout);
-
-/*******************************************************************************
- *
* Function L2CA_SubrateRequest
*
* Description BLE Subrate request.
diff --git a/system/stack/l2cap/l2c_api.h b/system/stack/l2cap/l2c_api.h
index 1ff09ffaf5..f9eab67d55 100644
--- a/system/stack/l2cap/l2c_api.h
+++ b/system/stack/l2cap/l2c_api.h
@@ -73,8 +73,6 @@ public:
uint8_t* p_chnl_mask) override;
[[nodiscard]] bool L2CA_SetAclPriority(const RawAddress& bd_addr,
tL2CAP_PRIORITY priority) override;
- void L2CA_SetDefaultSubrate(uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency,
- uint16_t cont_num, uint16_t timeout) override;
void L2CA_AdjustConnectionIntervals(uint16_t* min_interval, uint16_t* max_interval,
uint16_t floor_interval) override;
void L2CA_SetEcosystemBaseInterval(uint32_t base_interval) override;
diff --git a/system/stack/l2cap/l2c_ble.cc b/system/stack/l2cap/l2c_ble.cc
index 49dca969dc..d964271002 100644
--- a/system/stack/l2cap/l2c_ble.cc
+++ b/system/stack/l2cap/l2c_ble.cc
@@ -1443,7 +1443,7 @@ tL2CAP_LE_RESULT_CODE l2ble_sec_access_req(const RawAddress& bd_addr, uint16_t p
* constraints. For example, when there is at least one Hearing Aid device
* bonded, the minimum interval is raised. On return, min_interval and
* max_interval are updated. */
-void L2CA_AdjustConnectionIntervals(uint16_t* min_interval, uint16_t* max_interval,
+void L2CA_AdjustConnectionIntervals(uint16_t* /* min_interval */, uint16_t* max_interval,
uint16_t floor_interval) {
// Allow for customization by systemprops for mainline
uint16_t phone_min_interval = floor_interval;
@@ -1462,13 +1462,6 @@ void L2CA_AdjustConnectionIntervals(uint16_t* min_interval, uint16_t* max_interv
log::verbose("Have Hearing Aids. Min. interval is set to {}", phone_min_interval);
}
- if (!com::android::bluetooth::flags::l2cap_le_do_not_adjust_min_interval() &&
- *min_interval < phone_min_interval) {
- log::verbose("requested min_interval={} too small. Set to {}", *min_interval,
- phone_min_interval);
- *min_interval = phone_min_interval;
- }
-
// While this could result in connection parameters that fall
// outside fo the range requested, this will allow the connection
// to remain established.
diff --git a/system/stack/l2cap/l2c_ble_conn_params.cc b/system/stack/l2cap/l2c_ble_conn_params.cc
index 49eeb06155..392b1f5a74 100644
--- a/system/stack/l2cap/l2c_ble_conn_params.cc
+++ b/system/stack/l2cap/l2c_ble_conn_params.cc
@@ -510,26 +510,6 @@ static void l2cble_start_subrate_change(tL2C_LCB* p_lcb) {
/*******************************************************************************
*
- * Function L2CA_SetDefaultSubrate
- *
- * Description BLE Set Default Subrate
- *
- * Parameters: Subrate parameters
- *
- * Return value: void
- *
- ******************************************************************************/
-void L2CA_SetDefaultSubrate(uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency,
- uint16_t cont_num, uint16_t timeout) {
- log::verbose("subrate_min={}, subrate_max={}, max_latency={}, cont_num={}, timeout={}",
- subrate_min, subrate_max, max_latency, cont_num, timeout);
-
- bluetooth::shim::ACL_LeSetDefaultSubrate(subrate_min, subrate_max, max_latency, cont_num,
- timeout);
-}
-
-/*******************************************************************************
- *
* Function L2CA_SubrateRequest
*
* Description BLE Subrate request.
diff --git a/system/stack/l2cap/l2cap_api.cc b/system/stack/l2cap/l2cap_api.cc
index 0752c995c0..e9ccaeaf2a 100644
--- a/system/stack/l2cap/l2cap_api.cc
+++ b/system/stack/l2cap/l2cap_api.cc
@@ -234,13 +234,6 @@ void bluetooth::stack::l2cap::Impl::L2CA_SetEcosystemBaseInterval(uint32_t base_
return ::L2CA_IsLinkEstablished(bd_addr, transport);
}
-void bluetooth::stack::l2cap::Impl::L2CA_SetDefaultSubrate(uint16_t subrate_min,
- uint16_t subrate_max,
- uint16_t max_latency, uint16_t cont_num,
- uint16_t timeout) {
- ::L2CA_SetDefaultSubrate(subrate_min, subrate_max, max_latency, cont_num, timeout);
-}
-
[[nodiscard]] bool bluetooth::stack::l2cap::Impl::L2CA_SubrateRequest(
const RawAddress& rem_bda, uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency,
uint16_t cont_num, uint16_t timeout) {
diff --git a/system/stack/metrics/stack_metrics_logging.cc b/system/stack/metrics/stack_metrics_logging.cc
deleted file mode 100644
index 398a72ce33..0000000000
--- a/system/stack/metrics/stack_metrics_logging.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2021 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.
- */
-
-#include "stack/include/stack_metrics_logging.h"
-
-#include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
-#include <frameworks/proto_logging/stats/enums/bluetooth/hci/enums.pb.h>
-
-#include "common/metrics.h"
-#include "main/shim/metrics_api.h"
-#include "main/shim/shim.h"
-#include "types/raw_address.h"
-
-void log_classic_pairing_event(const RawAddress& address, uint16_t handle, uint32_t hci_cmd,
- uint16_t hci_event, uint16_t cmd_status, uint16_t reason_code,
- int64_t event_value) {
- bluetooth::shim::LogMetricClassicPairingEvent(address, handle, hci_cmd, hci_event, cmd_status,
- reason_code, event_value);
-}
-
-void log_link_layer_connection_event(const RawAddress* address, uint32_t connection_handle,
- android::bluetooth::DirectionEnum direction,
- uint16_t link_type, uint32_t hci_cmd, uint16_t hci_event,
- uint16_t hci_ble_event, uint16_t cmd_status,
- uint16_t reason_code) {
- bluetooth::shim::LogMetricLinkLayerConnectionEvent(address, connection_handle, direction,
- link_type, hci_cmd, hci_event, hci_ble_event,
- cmd_status, reason_code);
-}
-
-void log_smp_pairing_event(const RawAddress& address, uint16_t smp_cmd,
- android::bluetooth::DirectionEnum direction, uint16_t smp_fail_reason) {
- bluetooth::shim::LogMetricSmpPairingEvent(address, smp_cmd, direction, smp_fail_reason);
-}
-
-void log_sdp_attribute(const RawAddress& address, uint16_t protocol_uuid, uint16_t attribute_id,
- size_t attribute_size, const char* attribute_value) {
- bluetooth::shim::LogMetricSdpAttribute(address, protocol_uuid, attribute_id, attribute_size,
- attribute_value);
-}
-
-void log_manufacturer_info(const RawAddress& address,
- android::bluetooth::AddressTypeEnum address_type,
- android::bluetooth::DeviceInfoSrcEnum source_type,
- const std::string& source_name, const std::string& manufacturer,
- const std::string& model, const std::string& hardware_version,
- const std::string& software_version) {
- bluetooth::shim::LogMetricManufacturerInfo(address, address_type, source_type, source_name,
- manufacturer, model, hardware_version,
- software_version);
-}
-
-void log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum key, int64_t value) {
- bluetooth::shim::CountCounterMetrics(key, value);
-}
-
-void log_hfp_audio_packet_loss_stats(const RawAddress& address, int num_decoded_frames,
- double packet_loss_ratio, uint16_t codec_type) {
- bluetooth::shim::LogMetricHfpPacketLossStats(address, num_decoded_frames, packet_loss_ratio,
- codec_type);
-}
-
-void log_mmc_transcode_rtt_stats(int maximum_rtt, double mean_rtt, int num_requests,
- int codec_type) {
- bluetooth::shim::LogMetricMmcTranscodeRttStats(maximum_rtt, mean_rtt, num_requests, codec_type);
-}
-
-void log_le_pairing_fail(const RawAddress& raw_address, uint8_t failure_reason, bool is_outgoing) {
- bluetooth::shim::LogMetricLePairingFail(raw_address, failure_reason, is_outgoing);
-}
-
-void log_le_connection_status(bluetooth::hci::Address address, bool is_connect,
- bluetooth::hci::ErrorCode reason) {
- bluetooth::shim::LogMetricLeConnectionStatus(address, is_connect, reason);
-}
-
-void log_le_device_in_accept_list(bluetooth::hci::Address address, bool is_add) {
- bluetooth::shim::LogMetricLeDeviceInAcceptList(address, is_add);
-}
-
-void log_le_connection_lifecycle(bluetooth::hci::Address address, bool is_connect, bool is_direct) {
- bluetooth::shim::LogMetricLeConnectionLifecycle(address, is_connect, is_direct);
-}
-
-void log_le_connection_completion(bluetooth::hci::Address address, bluetooth::hci::ErrorCode reason,
- bool is_locally_initiated) {
- bluetooth::shim::LogMetricLeConnectionCompletion(address, reason, is_locally_initiated);
-}
diff --git a/system/stack/mmc/OWNERS b/system/stack/mmc/OWNERS
deleted file mode 100644
index a823e6e1dd..0000000000
--- a/system/stack/mmc/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /OWNERS_chromeos
diff --git a/system/stack/mmc/metrics/mmc_rtt_logger.cc b/system/stack/mmc/metrics/mmc_rtt_logger.cc
index 761d825b44..c95566f0cb 100644
--- a/system/stack/mmc/metrics/mmc_rtt_logger.cc
+++ b/system/stack/mmc/metrics/mmc_rtt_logger.cc
@@ -20,7 +20,7 @@
#include <cmath>
#include <string>
-#include "stack/include/stack_metrics_logging.h"
+#include "main/shim/metrics_api.h"
namespace mmc {
@@ -43,7 +43,8 @@ void MmcRttLogger::UploadTranscodeRttStatics() {
if (num_requests_ == 0) {
return;
}
- log_mmc_transcode_rtt_stats(maximum_rtt_, rtt_sum_ / num_requests_, num_requests_, codec_type_);
+ bluetooth::shim::LogMetricMmcTranscodeRttStats(maximum_rtt_, rtt_sum_ / num_requests_,
+ num_requests_, codec_type_);
num_requests_ = 0;
rtt_sum_ = 0;
maximum_rtt_ = 0;
diff --git a/system/stack/rfcomm/port_api.cc b/system/stack/rfcomm/port_api.cc
index a78f3ea890..6ab7cdccea 100644
--- a/system/stack/rfcomm/port_api.cc
+++ b/system/stack/rfcomm/port_api.cc
@@ -1229,7 +1229,9 @@ int PORT_GetChannelInfo(uint16_t handle, uint16_t* local_mtu, uint16_t* remote_m
return PORT_NOT_OPENED;
}
- if (p_port->line_status) {
+ if (p_port->rfc.p_mcb == nullptr || p_port->line_status) {
+ log::warn("PORT_LINE_ERR - p_port->rfc.p_mcb == nullptr:{} p_port->line_status:{}",
+ (p_port->rfc.p_mcb == nullptr) ? "T" : "F", p_port->line_status);
return PORT_LINE_ERR;
}
diff --git a/system/stack/rfcomm/port_rfc.cc b/system/stack/rfcomm/port_rfc.cc
index 860fdf0450..c1518665d9 100644
--- a/system/stack/rfcomm/port_rfc.cc
+++ b/system/stack/rfcomm/port_rfc.cc
@@ -36,12 +36,12 @@
#include "internal_include/bt_target.h"
#include "internal_include/bt_trace.h"
#include "main/shim/entry.h"
+#include "main/shim/metrics_api.h"
#include "osi/include/allocator.h"
#include "osi/include/mutex.h"
#include "stack/include/bt_hdr.h"
#include "stack/include/bt_uuid16.h"
#include "stack/include/rfc_metrics.h"
-#include "stack/include/stack_metrics_logging.h"
#include "stack/l2cap/l2c_int.h"
#include "stack/rfcomm/port_int.h"
#include "stack/rfcomm/rfc_int.h"
@@ -186,7 +186,8 @@ void port_start_close(tPORT* p_port) {
* clear tPort */
if (p_port->p_mgmt_callback) {
p_port->p_mgmt_callback(PORT_CLOSED, p_port->handle);
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_START_CLOSE, 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_START_CLOSE, 1);
}
port_release_port(p_port);
@@ -230,7 +231,7 @@ void PORT_StartCnf(tRFC_MCB* p_mcb, uint16_t result) {
if (p_port->p_mgmt_callback) {
p_port->p_mgmt_callback(PORT_START_FAILED, p_port->handle);
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_START_CNF_FAILED, 1);
}
port_release_port(p_port);
@@ -457,14 +458,14 @@ void PORT_DlcEstablishInd(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu) {
if (p_port->rfc_cfg_info.data_path != BTSOCK_DATA_PATH_HARDWARE_OFFLOAD &&
p_port->p_mgmt_callback) {
p_port->p_mgmt_callback(PORT_SUCCESS, p_port->handle);
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::RFCOMM_CONNECTION_SUCCESS_IND,
- 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::RFCOMM_CONNECTION_SUCCESS_IND, 1);
}
} else {
if (p_port->p_mgmt_callback) {
p_port->p_mgmt_callback(PORT_SUCCESS, p_port->handle);
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::RFCOMM_CONNECTION_SUCCESS_IND,
- 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::RFCOMM_CONNECTION_SUCCESS_IND, 1);
}
}
@@ -493,7 +494,8 @@ void PORT_DlcEstablishCnf(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu, uint16_t
if (result != RFCOMM_SUCCESS) {
log::warn("Unable to establish configuration dlci:{} result:{}", dlci, result);
port_rfc_closed(p_port, PORT_START_FAILED);
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_START_FAILED, 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_START_FAILED, 1);
return;
}
@@ -513,14 +515,14 @@ void PORT_DlcEstablishCnf(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu, uint16_t
if (p_port->rfc_cfg_info.data_path != BTSOCK_DATA_PATH_HARDWARE_OFFLOAD &&
p_port->p_mgmt_callback) {
p_port->p_mgmt_callback(PORT_SUCCESS, p_port->handle);
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::RFCOMM_CONNECTION_SUCCESS_CNF,
- 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::RFCOMM_CONNECTION_SUCCESS_CNF, 1);
}
} else {
if (p_port->p_mgmt_callback) {
p_port->p_mgmt_callback(PORT_SUCCESS, p_port->handle);
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::RFCOMM_CONNECTION_SUCCESS_CNF,
- 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::RFCOMM_CONNECTION_SUCCESS_CNF, 1);
}
}
@@ -590,7 +592,8 @@ void PORT_PortNegCnf(tRFC_MCB* p_mcb, uint8_t dlci, PortSettings* /* p_settings
RFCOMM_DlcReleaseReq(p_mcb, p_port->dlci);
port_rfc_closed(p_port, PORT_PORT_NEG_FAILED);
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_NEG_FAILED, 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_NEG_FAILED, 1);
return;
}
@@ -661,7 +664,7 @@ void PORT_ControlInd(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_CTRL* p_pars) {
if (p_port->rfc_cfg_info.data_path == BTSOCK_DATA_PATH_HARDWARE_OFFLOAD) {
if (p_port->port_ctrl == PORT_CTRL_SETUP_COMPLETED && p_port->p_mgmt_callback) {
p_port->p_mgmt_callback(PORT_SUCCESS, p_port->handle);
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::RFCOMM_CONNECTION_SUCCESS_IND, 1);
}
}
@@ -708,7 +711,7 @@ void PORT_ControlCnf(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_CTRL* /* p_pars */) {
if (p_port->rfc_cfg_info.data_path == BTSOCK_DATA_PATH_HARDWARE_OFFLOAD) {
if (p_port->port_ctrl == PORT_CTRL_SETUP_COMPLETED && p_port->p_mgmt_callback) {
p_port->p_mgmt_callback(PORT_SUCCESS, p_port->handle);
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::RFCOMM_CONNECTION_SUCCESS_CNF, 1);
}
}
@@ -767,7 +770,8 @@ void PORT_DlcReleaseInd(tRFC_MCB* p_mcb, uint8_t dlci) {
return;
}
port_rfc_closed(p_port, PORT_CLOSED);
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_CLOSED, 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_CLOSED, 1);
}
/*******************************************************************************
@@ -788,7 +792,7 @@ void PORT_CloseInd(tRFC_MCB* p_mcb) {
for (i = 0; i < MAX_RFC_PORTS; i++, p_port++) {
if (p_port->rfc.p_mcb == p_mcb) {
port_rfc_closed(p_port, PORT_PEER_CONNECTION_FAILED);
- log_counter_metrics(
+ bluetooth::shim::CountCounterMetrics(
android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_PEER_CONNECTION_FAILED, 1);
}
}
@@ -813,7 +817,8 @@ void PORT_TimeOutCloseMux(tRFC_MCB* p_mcb) {
for (i = 0; i < MAX_RFC_PORTS; i++, p_port++) {
if (p_port->rfc.p_mcb == p_mcb) {
port_rfc_closed(p_port, PORT_PEER_TIMEOUT);
- log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_PEER_TIMEOUT, 1);
+ bluetooth::shim::CountCounterMetrics(
+ android::bluetooth::CodePathCounterKeyEnum::RFCOMM_PORT_PEER_TIMEOUT, 1);
}
}
}
diff --git a/system/stack/rfcomm/rfc_l2cap_if.cc b/system/stack/rfcomm/rfc_l2cap_if.cc
index 5b7fc00185..10826d235a 100644
--- a/system/stack/rfcomm/rfc_l2cap_if.cc
+++ b/system/stack/rfcomm/rfc_l2cap_if.cc
@@ -91,28 +91,26 @@ void rfcomm_l2cap_if_init(void) {
void RFCOMM_ConnectInd(const RawAddress& bd_addr, uint16_t lcid, uint16_t /* psm */, uint8_t id) {
tRFC_MCB* p_mcb = rfc_alloc_multiplexer_channel(bd_addr, false);
- if ((p_mcb) && (p_mcb->state != RFC_MX_STATE_IDLE)) {
- /* if this is collision case */
- if ((p_mcb->is_initiator) && (p_mcb->state == RFC_MX_STATE_WAIT_CONN_CNF)) {
- p_mcb->pending_lcid = lcid;
-
- /* wait random timeout (2 - 12) to resolve collision */
- /* if peer gives up then local device rejects incoming connection and
- * continues as initiator */
- /* if timeout, local device disconnects outgoing connection and continues
- * as acceptor */
- log::verbose(
- "RFCOMM_ConnectInd start timer for collision, initiator's "
- "LCID(0x{:x}), acceptor's LCID(0x{:x})",
- p_mcb->lcid, p_mcb->pending_lcid);
-
- rfc_timer_start(p_mcb, (uint16_t)(bluetooth::common::time_get_os_boottime_ms() % 10 + 2));
- return;
- } else {
- /* we cannot accept connection request from peer at this state */
- /* don't update lcid */
- p_mcb = nullptr;
- }
+ if (p_mcb != nullptr && p_mcb->is_initiator && p_mcb->state == RFC_MX_STATE_WAIT_CONN_CNF) {
+ p_mcb->pending_lcid = lcid;
+
+ /* wait random timeout (2 - 12) to resolve collision */
+ /* if peer gives up then local device rejects incoming connection and
+ * continues as initiator */
+ /* if timeout, local device disconnects outgoing connection and continues
+ * as acceptor */
+ log::verbose(
+ "RFCOMM_ConnectInd start timer for collision, initiator's "
+ "LCID(0x{:x}), acceptor's LCID(0x{:x})",
+ p_mcb->lcid, p_mcb->pending_lcid);
+
+ rfc_timer_start(p_mcb, (uint16_t)(bluetooth::common::time_get_os_boottime_ms() % 10 + 2));
+ return;
+ }
+ if (p_mcb != nullptr && p_mcb->is_initiator && p_mcb->state != RFC_MX_STATE_IDLE) {
+ /* we cannot accept connection request from peer at this state */
+ /* don't update lcid */
+ p_mcb = nullptr;
} else {
/* store mcb even if null */
rfc_save_lcid_mcb(p_mcb, lcid);
@@ -141,7 +139,7 @@ void RFCOMM_ConnectInd(const RawAddress& bd_addr, uint16_t lcid, uint16_t /* psm
void RFCOMM_ConnectCnf(uint16_t lcid, tL2CAP_CONN result) {
tRFC_MCB* p_mcb = rfc_find_lcid_mcb(lcid);
- if (!p_mcb) {
+ if (p_mcb == nullptr) {
log::error("RFCOMM_ConnectCnf LCID:0x{:x}", lcid);
return;
}
@@ -188,7 +186,7 @@ void RFCOMM_ConfigInd(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
tRFC_MCB* p_mcb = rfc_find_lcid_mcb(lcid);
- if (!p_mcb) {
+ if (p_mcb == nullptr) {
log::error("RFCOMM_ConfigInd LCID:0x{:x}", lcid);
for (auto& [cid, mcb] : rfc_lcid_mcb) {
if (mcb != nullptr && mcb->pending_lcid == lcid) {
@@ -218,7 +216,7 @@ void RFCOMM_ConfigCnf(uint16_t lcid, uint16_t /* initiator */, tL2CAP_CFG_INFO*
tRFC_MCB* p_mcb = rfc_find_lcid_mcb(lcid);
- if (!p_mcb) {
+ if (p_mcb == nullptr) {
log::error("RFCOMM_ConfigCnf no MCB LCID:0x{:x}", lcid);
return;
}
@@ -237,7 +235,7 @@ void RFCOMM_ConfigCnf(uint16_t lcid, uint16_t /* initiator */, tL2CAP_CFG_INFO*
void RFCOMM_DisconnectInd(uint16_t lcid, bool is_conf_needed) {
log::verbose("lcid:0x{:x}, is_conf_needed:{}", lcid, is_conf_needed);
tRFC_MCB* p_mcb = rfc_find_lcid_mcb(lcid);
- if (!p_mcb) {
+ if (p_mcb == nullptr) {
log::warn("no mcb for lcid 0x{:x}", lcid);
return;
}
@@ -257,7 +255,7 @@ void RFCOMM_DisconnectInd(uint16_t lcid, bool is_conf_needed) {
void RFCOMM_BufDataInd(uint16_t lcid, BT_HDR* p_buf) {
tRFC_MCB* p_mcb = rfc_find_lcid_mcb(lcid);
- if (!p_mcb) {
+ if (p_mcb == nullptr) {
log::warn("Cannot find RFCOMM multiplexer for lcid 0x{:x}", lcid);
osi_free(p_buf);
return;
@@ -351,7 +349,7 @@ void RFCOMM_BufDataInd(uint16_t lcid, BT_HDR* p_buf) {
void RFCOMM_CongestionStatusInd(uint16_t lcid, bool is_congested) {
tRFC_MCB* p_mcb = rfc_find_lcid_mcb(lcid);
- if (!p_mcb) {
+ if (p_mcb == nullptr) {
log::error("RFCOMM_CongestionStatusInd dropped LCID:0x{:x}", lcid);
return;
} else {
diff --git a/system/stack/sdp/sdp_utils.cc b/system/stack/sdp/sdp_utils.cc
index 2fb4f4622b..324f4dd06e 100644
--- a/system/stack/sdp/sdp_utils.cc
+++ b/system/stack/sdp/sdp_utils.cc
@@ -39,6 +39,7 @@
#include "device/include/interop.h"
#include "internal_include/bt_target.h"
#include "internal_include/bt_trace.h"
+#include "main/shim/metrics_api.h"
#include "osi/include/allocator.h"
#include "osi/include/properties.h"
#include "stack/include/avrc_api.h"
@@ -50,7 +51,6 @@
#include "stack/include/btm_sec_api_types.h"
#include "stack/include/l2cap_interface.h"
#include "stack/include/sdpdefs.h"
-#include "stack/include/stack_metrics_logging.h"
#include "stack/sdp/internal/sdp_api.h"
#include "stack/sdp/sdpint.h"
#include "storage/config_keys.h"
@@ -184,15 +184,15 @@ void sdpu_log_attribute_metrics(const RawAddress& bda, tSDP_DISCOVERY_DB* p_db)
}
// Log the existence of a profile role
// This can be different from Bluetooth Profile Descriptor List
- log_sdp_attribute(bda, service_uuid, 0, 0, nullptr);
+ bluetooth::shim::LogMetricSdpAttribute(bda, service_uuid, 0, 0, nullptr);
// Log profile version from Bluetooth Profile Descriptor List
auto uuid_version_array = sdpu_find_profile_version(p_rec);
for (const auto& uuid_version_pair : uuid_version_array) {
uint16_t profile_uuid = uuid_version_pair.first;
uint16_t version = uuid_version_pair.second;
auto version_array = to_little_endian_array(version);
- log_sdp_attribute(bda, profile_uuid, ATTR_ID_BT_PROFILE_DESC_LIST, version_array.size(),
- version_array.data());
+ bluetooth::shim::LogMetricSdpAttribute(bda, profile_uuid, ATTR_ID_BT_PROFILE_DESC_LIST,
+ version_array.size(), version_array.data());
}
// Log protocol version from Protocol Descriptor List
uint16_t protocol_uuid = 0;
@@ -217,8 +217,8 @@ void sdpu_log_attribute_metrics(const RawAddress& bda, tSDP_DISCOVERY_DB* p_db)
if (protocol_elements.num_params >= 1) {
uint16_t version = protocol_elements.params[0];
auto version_array = to_little_endian_array(version);
- log_sdp_attribute(bda, protocol_uuid, ATTR_ID_PROTOCOL_DESC_LIST, version_array.size(),
- version_array.data());
+ bluetooth::shim::LogMetricSdpAttribute(bda, protocol_uuid, ATTR_ID_PROTOCOL_DESC_LIST,
+ version_array.size(), version_array.data());
}
}
}
@@ -238,8 +238,8 @@ void sdpu_log_attribute_metrics(const RawAddress& bda, tSDP_DISCOVERY_DB* p_db)
}
uint16_t supported_features = p_attr->attr_value.v.u16;
auto version_array = to_little_endian_array(supported_features);
- log_sdp_attribute(bda, service_uuid, ATTR_ID_SUPPORTED_FEATURES, version_array.size(),
- version_array.data());
+ bluetooth::shim::LogMetricSdpAttribute(bda, service_uuid, ATTR_ID_SUPPORTED_FEATURES,
+ version_array.size(), version_array.data());
break;
}
case UUID_SERVCLASS_MESSAGE_NOTIFICATION:
@@ -251,8 +251,8 @@ void sdpu_log_attribute_metrics(const RawAddress& bda, tSDP_DISCOVERY_DB* p_db)
}
uint32_t map_supported_features = p_attr->attr_value.v.u32;
auto features_array = to_little_endian_array(map_supported_features);
- log_sdp_attribute(bda, service_uuid, ATTR_ID_MAP_SUPPORTED_FEATURES, features_array.size(),
- features_array.data());
+ bluetooth::shim::LogMetricSdpAttribute(bda, service_uuid, ATTR_ID_MAP_SUPPORTED_FEATURES,
+ features_array.size(), features_array.data());
break;
}
case UUID_SERVCLASS_PBAP_PCE:
@@ -264,8 +264,8 @@ void sdpu_log_attribute_metrics(const RawAddress& bda, tSDP_DISCOVERY_DB* p_db)
}
uint32_t pbap_supported_features = p_attr->attr_value.v.u32;
auto features_array = to_little_endian_array(pbap_supported_features);
- log_sdp_attribute(bda, service_uuid, ATTR_ID_PBAP_SUPPORTED_FEATURES, features_array.size(),
- features_array.data());
+ bluetooth::shim::LogMetricSdpAttribute(bda, service_uuid, ATTR_ID_PBAP_SUPPORTED_FEATURES,
+ features_array.size(), features_array.data());
break;
}
}
@@ -278,15 +278,17 @@ void sdpu_log_attribute_metrics(const RawAddress& bda, tSDP_DISCOVERY_DB* p_db)
tSDP_DI_GET_RECORD di_record = {};
if (SDP_GetDiRecord(1, &di_record, p_db) == tSDP_STATUS::SDP_SUCCESS) {
auto version_array = to_little_endian_array(di_record.spec_id);
- log_sdp_attribute(bda, UUID_SERVCLASS_PNP_INFORMATION, ATTR_ID_SPECIFICATION_ID,
- version_array.size(), version_array.data());
+ bluetooth::shim::LogMetricSdpAttribute(bda, UUID_SERVCLASS_PNP_INFORMATION,
+ ATTR_ID_SPECIFICATION_ID, version_array.size(),
+ version_array.data());
std::stringstream ss;
// [N - native]::SDP::[DIP - Device ID Profile]
ss << "N:SDP::DIP::" << loghex(di_record.rec.vendor_id_source);
- log_manufacturer_info(bda, android::bluetooth::AddressTypeEnum::ADDRESS_TYPE_PUBLIC,
- android::bluetooth::DeviceInfoSrcEnum::DEVICE_INFO_INTERNAL, ss.str(),
- loghex(di_record.rec.vendor), loghex(di_record.rec.product),
- loghex(di_record.rec.version), "");
+ bluetooth::shim::LogMetricManufacturerInfo(
+ bda, android::bluetooth::AddressTypeEnum::ADDRESS_TYPE_PUBLIC,
+ android::bluetooth::DeviceInfoSrcEnum::DEVICE_INFO_INTERNAL, ss.str(),
+ loghex(di_record.rec.vendor), loghex(di_record.rec.product),
+ loghex(di_record.rec.version), "");
std::string bda_string = bda.ToString();
// write manufacturer, model, HW version to config
diff --git a/system/stack/smp/smp_l2c.cc b/system/stack/smp/smp_l2c.cc
index 219cb723f7..69591b10e5 100644
--- a/system/stack/smp/smp_l2c.cc
+++ b/system/stack/smp/smp_l2c.cc
@@ -263,13 +263,6 @@ static void smp_br_connect_callback(uint16_t /* channel */, const RawAddress& bd
log::info("BDA:{} pairing_bda:{}, connected:{}", bd_addr, p_cb->pairing_bda, connected);
if (bd_addr != p_cb->pairing_bda) {
- if (!com::android::bluetooth::flags::smp_state_machine_stuck_after_disconnection_fix()) {
- log::info(
- "If your pairing failed, get a build with "
- "smp_state_machine_stuck_after_disconnection_fix and try again :)");
- return;
- }
-
tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(bd_addr);
/* When pairing was initiated to RPA, and connection was on LE transport first using RPA, then
* we must check record pseudo address, it might be same device */
diff --git a/system/stack/smp/smp_utils.cc b/system/stack/smp/smp_utils.cc
index e5aefe3c6a..9be3de7db1 100644
--- a/system/stack/smp/smp_utils.cc
+++ b/system/stack/smp/smp_utils.cc
@@ -35,6 +35,7 @@
#include "internal_include/stack_config.h"
#include "main/shim/entry.h"
#include "main/shim/helpers.h"
+#include "main/shim/metrics_api.h"
#include "metrics/bluetooth_event.h"
#include "osi/include/allocator.h"
#include "p_256_ecc_pp.h"
@@ -51,7 +52,6 @@
#include "stack/include/l2cap_interface.h"
#include "stack/include/l2cdefs.h"
#include "stack/include/smp_status.h"
-#include "stack/include/stack_metrics_logging.h"
#include "types/raw_address.h"
#define SMP_PAIRING_REQ_SIZE 7
@@ -320,7 +320,7 @@ void smp_log_metrics(const RawAddress& bd_addr, bool is_outgoing, const uint8_t*
uint8_t failure_reason = 0;
if (raw_cmd == SMP_OPCODE_PAIRING_FAILED && buf_len >= 1) {
STREAM_TO_UINT8(failure_reason, p_buf);
- log_le_pairing_fail(bd_addr, failure_reason, is_outgoing);
+ bluetooth::shim::LogMetricLePairingFail(bd_addr, failure_reason, is_outgoing);
}
if (smp_cb.is_pair_cancel) {
failure_reason = SMP_USER_CANCELLED; // Tracking pairing cancellations
@@ -330,7 +330,8 @@ void smp_log_metrics(const RawAddress& bd_addr, bool is_outgoing, const uint8_t*
android::bluetooth::DirectionEnum direction =
is_outgoing ? android::bluetooth::DirectionEnum::DIRECTION_OUTGOING
: android::bluetooth::DirectionEnum::DIRECTION_INCOMING;
- log_smp_pairing_event(bd_addr, metric_cmd, direction, static_cast<uint16_t>(failure_reason));
+ bluetooth::shim::LogMetricSmpPairingEvent(bd_addr, metric_cmd, direction,
+ static_cast<uint16_t>(failure_reason));
}
/*******************************************************************************
@@ -1011,7 +1012,8 @@ void smp_proc_pairing_cmpl(tSMP_CB* p_cb) {
if (metric_status > SMP_MAX_FAIL_RSN_PER_SPEC) {
metric_status |= SMP_METRIC_STATUS_INTERNAL_FLAG;
}
- log_smp_pairing_event(p_cb->pairing_bda, metric_cmd, direction, metric_status);
+ bluetooth::shim::LogMetricSmpPairingEvent(p_cb->pairing_bda, metric_cmd, direction,
+ metric_status);
}
if (p_cb->status == SMP_SUCCESS && p_cb->smp_over_br) {
diff --git a/system/stack/test/btm/stack_btm_power_mode_test.cc b/system/stack/test/btm/stack_btm_power_mode_test.cc
index a3376d8649..ad7b27a71a 100644
--- a/system/stack/test/btm/stack_btm_power_mode_test.cc
+++ b/system/stack/test/btm/stack_btm_power_mode_test.cc
@@ -49,8 +49,10 @@ std::deque<power_mode_callback> power_mode_callback_queue;
class StackBtmPowerMode : public testing::Test {
protected:
void SetUp() override {
- ON_CALL(controller_, SupportsSniffMode).WillByDefault(Return(true));
- bluetooth::hci::testing::mock_controller_ = &controller_;
+ bluetooth::hci::testing::mock_controller_ =
+ std::make_unique<bluetooth::hci::testing::MockControllerInterface>();
+ ON_CALL(*bluetooth::hci::testing::mock_controller_, SupportsSniffMode)
+ .WillByDefault(Return(true));
power_mode_callback_queue.clear();
reset_mock_function_count_map();
ASSERT_EQ(tBTM_STATUS::BTM_SUCCESS,
@@ -71,10 +73,9 @@ protected:
BTM_PmRegister(BTM_PM_DEREG, &pm_id_,
[](const RawAddress& /* p_bda */, tBTM_PM_STATUS /* status */,
uint16_t /* value */, tHCI_STATUS /* hci_status */) {}));
- bluetooth::hci::testing::mock_controller_ = nullptr;
+ bluetooth::hci::testing::mock_controller_.reset();
}
- bluetooth::hci::testing::MockControllerInterface controller_;
uint8_t pm_id_{0};
};
diff --git a/system/stack/test/btm/stack_btm_sec_test.cc b/system/stack/test/btm/stack_btm_sec_test.cc
index 58317afc29..62226e2750 100644
--- a/system/stack/test/btm/stack_btm_sec_test.cc
+++ b/system/stack/test/btm/stack_btm_sec_test.cc
@@ -69,7 +69,8 @@ protected:
down_thread_ =
new bluetooth::os::Thread("down_thread", bluetooth::os::Thread::Priority::NORMAL);
down_handler_ = new bluetooth::os::Handler(down_thread_);
- bluetooth::hci::testing::mock_hci_layer_ = &mock_hci_;
+ bluetooth::hci::testing::mock_hci_layer_ =
+ std::make_unique<bluetooth::hci::testing::MockHciLayer>();
bluetooth::hci::testing::mock_gd_shim_handler_ = up_handler_;
}
void TearDown() override {
@@ -79,10 +80,10 @@ protected:
down_handler_->Clear();
delete down_handler_;
delete down_thread_;
+ bluetooth::hci::testing::mock_hci_layer_.reset();
StackBtmSecTest::TearDown();
}
bluetooth::common::BidiQueue<bluetooth::hci::ScoView, bluetooth::hci::ScoBuilder> sco_queue_{10};
- bluetooth::hci::testing::MockHciLayer mock_hci_;
bluetooth::os::Thread* up_thread_;
bluetooth::os::Handler* up_handler_;
bluetooth::os::Thread* down_thread_;
diff --git a/system/stack/test/btm/stack_btm_test.cc b/system/stack/test/btm/stack_btm_test.cc
index 7471d4faca..2341b21677 100644
--- a/system/stack/test/btm/stack_btm_test.cc
+++ b/system/stack/test/btm/stack_btm_test.cc
@@ -63,13 +63,13 @@ public:
protected:
void SetUp() override {
BtmWithMocksTest::SetUp();
- bluetooth::hci::testing::mock_controller_ = &controller_;
+ bluetooth::hci::testing::mock_controller_ =
+ std::make_unique<bluetooth::hci::testing::MockControllerInterface>();
}
void TearDown() override {
- bluetooth::hci::testing::mock_controller_ = nullptr;
+ bluetooth::hci::testing::mock_controller_.reset();
BtmWithMocksTest::TearDown();
}
- bluetooth::hci::testing::MockControllerInterface controller_;
};
class StackBtmWithQueuesTest : public StackBtmTest {
@@ -82,11 +82,12 @@ protected:
down_thread_ =
new bluetooth::os::Thread("down_thread", bluetooth::os::Thread::Priority::NORMAL);
down_handler_ = new bluetooth::os::Handler(down_thread_);
- bluetooth::hci::testing::mock_hci_layer_ = &mock_hci_;
+ bluetooth::hci::testing::mock_hci_layer_ =
+ std::make_unique<bluetooth::hci::testing::MockHciLayer>();
bluetooth::hci::testing::mock_gd_shim_handler_ = up_handler_;
bluetooth::legacy::hci::testing::SetMock(legacy_hci_mock_);
- EXPECT_CALL(mock_hci_, RegisterForScoConnectionRequests(_));
- EXPECT_CALL(mock_hci_, RegisterForDisconnects(_));
+ EXPECT_CALL(*bluetooth::hci::testing::mock_hci_layer_, RegisterForScoConnectionRequests(_));
+ EXPECT_CALL(*bluetooth::hci::testing::mock_hci_layer_, RegisterForDisconnects(_));
}
void TearDown() override {
up_handler_->Clear();
@@ -95,10 +96,10 @@ protected:
down_handler_->Clear();
delete down_handler_;
delete down_thread_;
+ bluetooth::hci::testing::mock_hci_layer_.release();
StackBtmTest::TearDown();
}
bluetooth::common::BidiQueue<bluetooth::hci::ScoView, bluetooth::hci::ScoBuilder> sco_queue_{10};
- bluetooth::hci::testing::MockHciLayer mock_hci_;
bluetooth::legacy::hci::testing::MockInterface legacy_hci_mock_;
bluetooth::os::Thread* up_thread_;
bluetooth::os::Handler* up_handler_;
@@ -111,7 +112,8 @@ public:
protected:
void SetUp() override {
StackBtmWithQueuesTest::SetUp();
- EXPECT_CALL(mock_hci_, GetScoQueueEnd()).WillOnce(Return(sco_queue_.GetUpEnd()));
+ EXPECT_CALL(*bluetooth::hci::testing::mock_hci_layer_, GetScoQueueEnd())
+ .WillOnce(Return(sco_queue_.GetUpEnd()));
btm_cb.Init();
btm_sec_cb.Init(BTM_SEC_MODE_SC);
}
@@ -123,7 +125,8 @@ protected:
};
TEST_F(StackBtmWithQueuesTest, GlobalLifecycle) {
- EXPECT_CALL(mock_hci_, GetScoQueueEnd()).WillOnce(Return(sco_queue_.GetUpEnd()));
+ EXPECT_CALL(*bluetooth::hci::testing::mock_hci_layer_, GetScoQueueEnd())
+ .WillOnce(Return(sco_queue_.GetUpEnd()));
get_btm_client_interface().lifecycle.btm_init();
get_btm_client_interface().lifecycle.btm_free();
}
@@ -134,20 +137,23 @@ TEST_F(StackBtmTest, DynamicLifecycle) {
}
TEST_F(StackBtmWithQueuesTest, InitFree) {
- EXPECT_CALL(mock_hci_, GetScoQueueEnd()).WillOnce(Return(sco_queue_.GetUpEnd()));
+ EXPECT_CALL(*bluetooth::hci::testing::mock_hci_layer_, GetScoQueueEnd())
+ .WillOnce(Return(sco_queue_.GetUpEnd()));
btm_cb.Init();
btm_cb.Free();
}
TEST_F(StackBtmWithQueuesTest, tSCO_CB) {
- EXPECT_CALL(mock_hci_, GetScoQueueEnd()).WillOnce(Return(sco_queue_.GetUpEnd()));
+ EXPECT_CALL(*bluetooth::hci::testing::mock_hci_layer_, GetScoQueueEnd())
+ .WillOnce(Return(sco_queue_.GetUpEnd()));
tSCO_CB* p_sco = &btm_cb.sco_cb;
p_sco->Init();
p_sco->Free();
}
TEST_F(StackBtmWithQueuesTest, InformClientOnConnectionSuccess) {
- EXPECT_CALL(mock_hci_, GetScoQueueEnd()).WillOnce(Return(sco_queue_.GetUpEnd()));
+ EXPECT_CALL(*bluetooth::hci::testing::mock_hci_layer_, GetScoQueueEnd())
+ .WillOnce(Return(sco_queue_.GetUpEnd()));
get_btm_client_interface().lifecycle.btm_init();
RawAddress bda({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
@@ -159,7 +165,8 @@ TEST_F(StackBtmWithQueuesTest, InformClientOnConnectionSuccess) {
}
TEST_F(StackBtmWithQueuesTest, NoInformClientOnConnectionFail) {
- EXPECT_CALL(mock_hci_, GetScoQueueEnd()).WillOnce(Return(sco_queue_.GetUpEnd()));
+ EXPECT_CALL(*bluetooth::hci::testing::mock_hci_layer_, GetScoQueueEnd())
+ .WillOnce(Return(sco_queue_.GetUpEnd()));
get_btm_client_interface().lifecycle.btm_init();
RawAddress bda({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
@@ -171,7 +178,8 @@ TEST_F(StackBtmWithQueuesTest, NoInformClientOnConnectionFail) {
}
TEST_F(StackBtmWithQueuesTest, default_packet_type) {
- EXPECT_CALL(mock_hci_, GetScoQueueEnd()).WillOnce(Return(sco_queue_.GetUpEnd()));
+ EXPECT_CALL(*bluetooth::hci::testing::mock_hci_layer_, GetScoQueueEnd())
+ .WillOnce(Return(sco_queue_.GetUpEnd()));
get_btm_client_interface().lifecycle.btm_init();
btm_cb.acl_cb_.SetDefaultPacketTypeMask(0x4321);
@@ -181,7 +189,8 @@ TEST_F(StackBtmWithQueuesTest, default_packet_type) {
}
TEST_F(StackBtmWithQueuesTest, change_packet_type) {
- EXPECT_CALL(mock_hci_, GetScoQueueEnd()).WillOnce(Return(sco_queue_.GetUpEnd()));
+ EXPECT_CALL(*bluetooth::hci::testing::mock_hci_layer_, GetScoQueueEnd())
+ .WillOnce(Return(sco_queue_.GetUpEnd()));
get_btm_client_interface().lifecycle.btm_init();
uint16_t handle = 0x123;
diff --git a/system/stack/test/btm_iso_test.cc b/system/stack/test/btm_iso_test.cc
index 40453f703d..b44f6fe094 100644
--- a/system/stack/test/btm_iso_test.cc
+++ b/system/stack/test/btm_iso_test.cc
@@ -134,7 +134,8 @@ protected:
bluetooth::shim::SetMockIsoInterface(&iso_interface_);
hcic::SetMockHcicInterface(&hcic_interface_);
bluetooth::shim::testing::hci_layer_set_interface(&bluetooth::shim::interface);
- bluetooth::hci::testing::mock_controller_ = &controller_;
+ bluetooth::hci::testing::mock_controller_ =
+ std::make_unique<bluetooth::hci::testing::MockControllerInterface>();
big_callbacks_.reset(new MockBigCallbacks());
cig_callbacks_.reset(new MockCigCallbacks());
@@ -142,7 +143,8 @@ protected:
iso_sizes_.total_num_le_packets_ = 6;
iso_sizes_.le_data_packet_length_ = 1024;
- ON_CALL(controller_, GetControllerIsoBufferSize()).WillByDefault(Return(iso_sizes_));
+ ON_CALL(*bluetooth::hci::testing::mock_controller_, GetControllerIsoBufferSize())
+ .WillByDefault(Return(iso_sizes_));
InitIsoManager();
}
@@ -156,7 +158,7 @@ protected:
bluetooth::shim::SetMockIsoInterface(nullptr);
hcic::SetMockHcicInterface(nullptr);
bluetooth::shim::testing::hci_layer_set_interface(nullptr);
- bluetooth::hci::testing::mock_controller_ = nullptr;
+ bluetooth::hci::testing::mock_controller_.reset();
}
virtual void InitIsoManager() {
@@ -312,7 +314,6 @@ protected:
IsoManager* manager_instance_;
bluetooth::shim::MockIsoInterface iso_interface_;
hcic::MockHcicInterface hcic_interface_;
- bluetooth::hci::testing::MockControllerInterface controller_;
bluetooth::hci::LeBufferSize iso_sizes_;
std::unique_ptr<MockBigCallbacks> big_callbacks_;
@@ -2207,7 +2208,8 @@ TEST_F(IsoManagerTest, SendIsoDataBigValid) {
}
TEST_F(IsoManagerTest, SendIsoDataNoCredits) {
- uint8_t num_buffers = controller_.GetControllerIsoBufferSize().total_num_le_packets_;
+ uint8_t num_buffers = bluetooth::hci::testing::mock_controller_->GetControllerIsoBufferSize()
+ .total_num_le_packets_;
std::vector<uint8_t> data_vec(108, 0);
// Check on CIG
@@ -2254,7 +2256,8 @@ TEST_F(IsoManagerTest, SendIsoDataNoCredits) {
}
TEST_F(IsoManagerTest, SendIsoDataCreditsReturned) {
- uint8_t num_buffers = controller_.GetControllerIsoBufferSize().total_num_le_packets_;
+ uint8_t num_buffers = bluetooth::hci::testing::mock_controller_->GetControllerIsoBufferSize()
+ .total_num_le_packets_;
std::vector<uint8_t> data_vec(108, 0);
// Check on CIG
@@ -2323,7 +2326,8 @@ TEST_F(IsoManagerTest, SendIsoDataCreditsReturned) {
}
TEST_F(IsoManagerTest, SendIsoDataCreditsReturnedByDisconnection) {
- uint8_t num_buffers = controller_.GetControllerIsoBufferSize().total_num_le_packets_;
+ uint8_t num_buffers = bluetooth::hci::testing::mock_controller_->GetControllerIsoBufferSize()
+ .total_num_le_packets_;
std::vector<uint8_t> data_vec(108, 0);
// Check on CIG
@@ -2542,7 +2546,8 @@ TEST_F(IsoManagerDeathTestNoCleanup, HandleLateArivingEventHandleDisconnect) {
* is already stopped.
*/
TEST_F(IsoManagerDeathTestNoCleanup, HandleLateArivingEventHandleNumComplDataPkts) {
- uint8_t num_buffers = controller_.GetControllerIsoBufferSize().total_num_le_packets_;
+ uint8_t num_buffers = bluetooth::hci::testing::mock_controller_->GetControllerIsoBufferSize()
+ .total_num_le_packets_;
IsoManager::GetInstance()->CreateCig(volatile_test_cig_create_cmpl_evt_.cig_id,
kDefaultCigParams);
diff --git a/system/stack/test/connection_manager_test.cc b/system/stack/test/connection_manager_test.cc
index 1a06158ca0..db2908c76b 100644
--- a/system/stack/test/connection_manager_test.cc
+++ b/system/stack/test/connection_manager_test.cc
@@ -70,9 +70,10 @@ namespace connection_manager {
class BleConnectionManager : public testing::Test {
void SetUp() override {
localConnTimeoutMock = std::make_unique<MockConnTimeout>();
- /* extern */ test::mock_acl_manager_ = new bluetooth::hci::testing::MockAclManager();
+ /* extern */ test::mock_acl_manager_ =
+ std::make_unique<bluetooth::hci::testing::MockAclManager>();
/* extern */ test::mock_controller_ =
- new testing::NiceMock<bluetooth::hci::testing::MockControllerInterface>();
+ std::make_unique<testing::NiceMock<bluetooth::hci::testing::MockControllerInterface>>();
ON_CALL(*test::mock_controller_, GetLeFilterAcceptListSize()).WillByDefault(Return(16));
auto alarm_mock = AlarmMock::Get();
@@ -92,8 +93,8 @@ class BleConnectionManager : public testing::Test {
void TearDown() override {
connection_manager::reset(true);
AlarmMock::Reset();
- delete test::mock_controller_;
- delete test::mock_acl_manager_;
+ test::mock_controller_.reset();
+ test::mock_acl_manager_.reset();
localConnTimeoutMock.reset();
}
};
@@ -106,7 +107,7 @@ TEST_F(BleConnectionManager, test_background_connection_add_remove) {
EXPECT_TRUE(background_connect_add(CLIENT1, address1));
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
std::set<tAPP_ID> apps = get_apps_connecting_to(address1);
EXPECT_EQ(apps.size(), 1UL);
@@ -119,7 +120,7 @@ TEST_F(BleConnectionManager, test_background_connection_add_remove) {
EXPECT_EQ(get_apps_connecting_to(address1).size(), 0UL);
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
}
/** Verify that multiple clients adding same device multiple times, result in
@@ -136,7 +137,7 @@ TEST_F(BleConnectionManager, test_background_connection_multiple_clients) {
EXPECT_EQ(get_apps_connecting_to(address1).size(), 3UL);
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
EXPECT_CALL(*test::mock_acl_manager_, CreateLeConnection(_, _)).Times(0);
@@ -153,7 +154,7 @@ TEST_F(BleConnectionManager, test_background_connection_multiple_clients) {
EXPECT_EQ(get_apps_connecting_to(address1).size(), 0UL);
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
}
/** Verify adding/removing device to direct connection. */
@@ -173,7 +174,7 @@ TEST_F(BleConnectionManager, test_direct_connection_client) {
// Client that don't do direct connection should fail attempt to stop it
EXPECT_FALSE(direct_connect_remove(CLIENT2, address1));
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
EXPECT_CALL(*test::mock_acl_manager_, CancelLeConnect(_)).Times(1);
EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1);
@@ -183,7 +184,7 @@ TEST_F(BleConnectionManager, test_direct_connection_client) {
// acceptlist is in use, i.e. next connection attempt
EXPECT_TRUE(direct_connect_remove(CLIENT1, address1));
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
}
/** Verify direct connection timeout does remove device from acceptlist, and
@@ -201,7 +202,7 @@ TEST_F(BleConnectionManager, test_direct_connect_timeout) {
// Start direct connect attempt...
EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
EXPECT_CALL(*test::mock_acl_manager_, CancelLeConnect(_)).Times(1);
EXPECT_CALL(*localConnTimeoutMock, OnConnectionTimedOut(CLIENT1, address1)).Times(1);
@@ -210,7 +211,7 @@ TEST_F(BleConnectionManager, test_direct_connect_timeout) {
// simulate timeout seconds passed, alarm executing
alarm_callback(alarm_data);
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
}
/** Verify that we properly handle successfull direct connection */
@@ -222,7 +223,7 @@ TEST_F(BleConnectionManager, test_direct_connection_success) {
// Start direct connect attempt...
EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
EXPECT_CALL(*test::mock_acl_manager_, CancelLeConnect(address1_hci)).Times(1);
EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1);
@@ -230,7 +231,7 @@ TEST_F(BleConnectionManager, test_direct_connection_success) {
// successfully.
on_connection_complete(address1);
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
}
/** Verify that we properly handle application unregistration */
@@ -244,23 +245,23 @@ TEST_F(BleConnectionManager, test_app_unregister) {
EXPECT_CALL(*test::mock_acl_manager_, CreateLeConnection(address1_hci, true)).Times(1);
EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
EXPECT_CALL(*test::mock_acl_manager_, CreateLeConnection(address2_hci, false)).Times(1);
EXPECT_TRUE(background_connect_add(CLIENT1, address2));
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
EXPECT_CALL(*test::mock_acl_manager_, CreateLeConnection(address2_hci, true)).Times(1);
EXPECT_TRUE(direct_connect_add(CLIENT2, address2));
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
EXPECT_CALL(*test::mock_acl_manager_, CancelLeConnect(address1_hci)).Times(1);
on_app_deregistered(CLIENT1);
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
EXPECT_CALL(*test::mock_acl_manager_, CancelLeConnect(address2_hci)).Times(1);
on_app_deregistered(CLIENT2);
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
}
/** Verify adding device to both direct connection and background connection. */
@@ -273,7 +274,7 @@ TEST_F(BleConnectionManager, test_direct_and_background_connect) {
EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
EXPECT_TRUE(background_connect_add(CLIENT1, address1));
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1);
// not removing from acceptlist yet, as the background connection is still
@@ -284,7 +285,7 @@ TEST_F(BleConnectionManager, test_direct_and_background_connect) {
EXPECT_CALL(*test::mock_acl_manager_, CancelLeConnect(_)).Times(1);
EXPECT_TRUE(background_connect_remove(CLIENT1, address1));
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
}
TEST_F(BleConnectionManager, test_target_announement_connect) {
@@ -302,7 +303,7 @@ TEST_F(BleConnectionManager, test_add_targeted_announement_when_allow_list_used)
EXPECT_TRUE(background_connect_add(CLIENT1, address1));
EXPECT_TRUE(background_connect_targeted_announcement_add(CLIENT2, address1));
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
}
TEST_F(BleConnectionManager, test_add_background_connect_when_targeted_announcement_are_enabled) {
@@ -315,7 +316,7 @@ TEST_F(BleConnectionManager, test_add_background_connect_when_targeted_announcem
EXPECT_TRUE(background_connect_targeted_announcement_add(CLIENT2, address1));
EXPECT_TRUE(background_connect_add(CLIENT1, address1));
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
}
TEST_F(BleConnectionManager, test_re_add_background_connect_to_allow_list) {
@@ -325,7 +326,7 @@ TEST_F(BleConnectionManager, test_re_add_background_connect_to_allow_list) {
EXPECT_TRUE(background_connect_targeted_announcement_add(CLIENT2, address1));
EXPECT_TRUE(background_connect_add(CLIENT1, address1));
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
/* Now remove app using targeted announcement and expect device
* to be added to white list
@@ -335,11 +336,11 @@ TEST_F(BleConnectionManager, test_re_add_background_connect_to_allow_list) {
EXPECT_CALL(*test::mock_acl_manager_, CreateLeConnection(address1_hci, false)).Times(1);
EXPECT_TRUE(background_connect_remove(CLIENT2, address1));
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
EXPECT_CALL(*test::mock_acl_manager_, CancelLeConnect(_)).Times(1);
EXPECT_TRUE(background_connect_remove(CLIENT1, address1));
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
}
TEST_F(BleConnectionManager, test_re_add_to_allow_list_after_timeout_with_multiple_clients) {
@@ -352,7 +353,7 @@ TEST_F(BleConnectionManager, test_re_add_to_allow_list_after_timeout_with_multip
EXPECT_TRUE(background_connect_add(CLIENT1, address1));
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _))
.Times(1)
@@ -360,7 +361,7 @@ TEST_F(BleConnectionManager, test_re_add_to_allow_list_after_timeout_with_multip
// Start direct connect attempt...
EXPECT_TRUE(direct_connect_add(CLIENT2, address1));
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
// simulate timeout seconds passed, alarm executing
EXPECT_CALL(*localConnTimeoutMock, OnConnectionTimedOut(CLIENT2, address1)).Times(1);
@@ -369,7 +370,7 @@ TEST_F(BleConnectionManager, test_re_add_to_allow_list_after_timeout_with_multip
EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1);
alarm_callback(alarm_data);
- Mock::VerifyAndClearExpectations(test::mock_acl_manager_);
+ Mock::VerifyAndClearExpectations(test::mock_acl_manager_.get());
}
} // namespace connection_manager
diff --git a/system/stack/test/eatt/eatt_test.cc b/system/stack/test/eatt/eatt_test.cc
index 130893a0a5..17f4908b3e 100644
--- a/system/stack/test/eatt/eatt_test.cc
+++ b/system/stack/test/eatt/eatt_test.cc
@@ -219,11 +219,13 @@ protected:
le_buffer_size_.le_data_packet_length_ = 128;
le_buffer_size_.total_num_le_packets_ = 24;
- EXPECT_CALL(controller_, GetLeBufferSize).WillRepeatedly(Return(le_buffer_size_));
+ bluetooth::hci::testing::mock_controller_ =
+ std::make_unique<bluetooth::hci::testing::MockControllerInterface>();
+ EXPECT_CALL(*bluetooth::hci::testing::mock_controller_, GetLeBufferSize)
+ .WillRepeatedly(Return(le_buffer_size_));
bluetooth::l2cap::SetMockInterface(&l2cap_interface_);
bluetooth::manager::SetMockBtmApiInterface(&btm_api_interface_);
bluetooth::gatt::SetMockGattInterface(&gatt_interface_);
- bluetooth::hci::testing::mock_controller_ = &controller_;
// Clear the static memory for each test case
memset(&test_tcb, 0, sizeof(test_tcb));
@@ -258,7 +260,7 @@ protected:
bluetooth::l2cap::SetMockInterface(nullptr);
bluetooth::testing::stack::l2cap::reset_interface();
bluetooth::manager::SetMockBtmApiInterface(nullptr);
- bluetooth::hci::testing::mock_controller_ = nullptr;
+ bluetooth::hci::testing::mock_controller_.reset();
Test::TearDown();
}
@@ -269,7 +271,6 @@ protected:
bluetooth::l2cap::MockL2capInterface l2cap_interface_;
bluetooth::testing::stack::l2cap::Mock mock_stack_l2cap_interface_;
bluetooth::gatt::MockGattInterface gatt_interface_;
- bluetooth::hci::testing::MockControllerInterface controller_;
bluetooth::hci::LeBufferSize le_buffer_size_;
tL2CAP_APPL_INFO l2cap_app_info_;
@@ -659,7 +660,6 @@ TEST_F(EattTest, ChannelUnavailableWhileReconfiguring) {
}
TEST_F(EattTest, DisconnectChannelOnIndicationConfirmationTimeout) {
- com::android::bluetooth::flags::provider_->gatt_disconnect_fix(true);
ConnectDeviceEattSupported(1);
eatt_instance_->StartIndicationConfirmationTimer(test_address, test_local_cids[0]);
diff --git a/system/stack/test/gatt/gatt_sr_test.cc b/system/stack/test/gatt/gatt_sr_test.cc
index 9c5eb868d0..4106579080 100644
--- a/system/stack/test/gatt/gatt_sr_test.cc
+++ b/system/stack/test/gatt/gatt_sr_test.cc
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <com_android_bluetooth_flags.h>
#include <gtest/gtest.h>
#include <cstdint>
@@ -141,25 +140,16 @@ protected:
tcb_.att_lcid = L2CAP_ATT_CID;
el_.gatt_if = 1;
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- gatt_cb.cl_rcb_map.emplace(el_.gatt_if, std::make_unique<tGATT_REG>());
- tGATT_REG* p_reg = gatt_cb.cl_rcb_map[el_.gatt_if].get();
- p_reg->in_use = true;
- p_reg->gatt_if = el_.gatt_if;
- p_reg->app_cb.p_req_cb = ApplicationRequestCallback;
- } else {
- gatt_cb.cl_rcb[el_.gatt_if - 1].in_use = true;
- gatt_cb.cl_rcb[el_.gatt_if - 1].app_cb.p_req_cb = ApplicationRequestCallback;
- }
+ gatt_cb.cl_rcb_map.emplace(el_.gatt_if, std::make_unique<tGATT_REG>());
+ tGATT_REG* p_reg = gatt_cb.cl_rcb_map[el_.gatt_if].get();
+ p_reg->in_use = true;
+ p_reg->gatt_if = el_.gatt_if;
+ p_reg->app_cb.p_req_cb = ApplicationRequestCallback;
test_state_ = TestMutables();
}
- void TearDown() override {
- if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) {
- gatt_cb.cl_rcb_map.erase(el_.gatt_if);
- }
- }
+ void TearDown() override { gatt_cb.cl_rcb_map.erase(el_.gatt_if); }
tGATT_TCB tcb_;
tGATT_SRV_LIST_ELEM el_;
diff --git a/system/stack/test/sdp/stack_sdp_test.cc b/system/stack/test/sdp/stack_sdp_test.cc
index 314ea02334..c792a5fd0d 100644
--- a/system/stack/test/sdp/stack_sdp_test.cc
+++ b/system/stack/test/sdp/stack_sdp_test.cc
@@ -62,7 +62,6 @@ protected:
fake_osi_ = std::make_unique<test::fake::FakeOsi>();
bluetooth::testing::stack::l2cap::set_interface(&mock_stack_l2cap_interface_);
- tL2CAP_APPL_INFO l2cap_callbacks{};
EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_RegisterWithSecurity(_, _, _, _, _, _, _))
.WillOnce(DoAll(SaveArg<1>(&l2cap_callbacks), ::testing::ReturnArg<0>()));
EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(_));
@@ -73,6 +72,7 @@ protected:
fake_osi_.reset();
}
+ tL2CAP_APPL_INFO l2cap_callbacks{};
bluetooth::testing::stack::l2cap::Mock mock_stack_l2cap_interface_;
std::unique_ptr<test::fake::FakeOsi> fake_osi_;
};
diff --git a/system/stack/test/stack_acl_test.cc b/system/stack/test/stack_acl_test.cc
index b08a45cb80..bd0b153b9f 100644
--- a/system/stack/test/stack_acl_test.cc
+++ b/system/stack/test/stack_acl_test.cc
@@ -48,12 +48,12 @@ class StackAclTest : public testing::Test {
protected:
void SetUp() override {
reset_mock_function_count_map();
- bluetooth::hci::testing::mock_controller_ = &controller_;
+ bluetooth::hci::testing::mock_controller_ =
+ std::make_unique<bluetooth::hci::testing::MockControllerInterface>();
}
- void TearDown() override { bluetooth::hci::testing::mock_controller_ = nullptr; }
+ void TearDown() override { bluetooth::hci::testing::mock_controller_.reset(); }
tBTM_SEC_DEV_REC device_record_;
- bluetooth::hci::testing::MockControllerInterface controller_;
};
TEST_F(StackAclTest, nop) {}
diff --git a/system/stack/test/stack_l2cap_test.cc b/system/stack/test/stack_l2cap_test.cc
index ffe78055bc..204900b462 100644
--- a/system/stack/test/stack_l2cap_test.cc
+++ b/system/stack/test/stack_l2cap_test.cc
@@ -49,23 +49,23 @@ constexpr uint16_t kAclBufferSizeBle = 45;
class StackL2capTest : public ::testing::Test {
protected:
void SetUp() override {
- bluetooth::hci::testing::mock_controller_ = &controller_interface_;
- ON_CALL(controller_interface_, GetNumAclPacketBuffers)
+ bluetooth::hci::testing::mock_controller_ =
+ std::make_unique<bluetooth::hci::testing::MockControllerInterface>();
+ ON_CALL(*bluetooth::hci::testing::mock_controller_, GetNumAclPacketBuffers)
.WillByDefault(Return(kAclBufferCountClassic));
bluetooth::hci::LeBufferSize le_sizes;
le_sizes.total_num_le_packets_ = kAclBufferCountBle;
le_sizes.le_data_packet_length_ = kAclBufferSizeBle;
- ON_CALL(controller_interface_, GetLeBufferSize).WillByDefault(Return(le_sizes));
- ON_CALL(controller_interface_, SupportsBle).WillByDefault(Return(true));
+ ON_CALL(*bluetooth::hci::testing::mock_controller_, GetLeBufferSize)
+ .WillByDefault(Return(le_sizes));
+ ON_CALL(*bluetooth::hci::testing::mock_controller_, SupportsBle).WillByDefault(Return(true));
l2c_init();
}
void TearDown() override {
l2c_free();
- bluetooth::hci::testing::mock_controller_ = nullptr;
+ bluetooth::hci::testing::mock_controller_.reset();
}
-
- bluetooth::hci::testing::MockControllerInterface controller_interface_;
};
TEST_F(StackL2capTest, l2cble_process_data_length_change_event) {
diff --git a/system/test/Android.bp b/system/test/Android.bp
index c35931ea17..9dab01352f 100644
--- a/system/test/Android.bp
+++ b/system/test/Android.bp
@@ -88,6 +88,13 @@ filegroup {
}
filegroup {
+ name: "TestMockBtaHearingAidAudioSource",
+ srcs: [
+ "mock/mock_bta_hearing_aid_audio_source.cc",
+ ],
+}
+
+filegroup {
name: "TestMockBtaHf",
srcs: [
"mock/mock_bta_hf*.cc",
@@ -184,6 +191,7 @@ filegroup {
":TestMockBtaHas",
":TestMockBtaHd",
":TestMockBtaHearingAid",
+ ":TestMockBtaHearingAidAudioSource",
":TestMockBtaHf",
":TestMockBtaHh",
":TestMockBtaJv",
@@ -450,16 +458,16 @@ filegroup {
}
filegroup {
- name: "TestMockStackMetrics",
+ name: "TestMockStackGap",
srcs: [
- "mock/mock_stack_metrics*.cc",
+ "mock/mock_stack_gap*.cc",
],
}
filegroup {
- name: "TestMockStackGap",
+ name: "TestMockStackGapConnInterface",
srcs: [
- "mock/mock_stack_gap*.cc",
+ "mock/mock_stack_gap_conn_interface.cc",
],
}
diff --git a/system/test/README.md b/system/test/README.md
deleted file mode 100644
index 1f43e952ef..0000000000
--- a/system/test/README.md
+++ /dev/null
@@ -1,81 +0,0 @@
-# Fluoride Bluetooth Tests
-
-This document refers to the tests in the packages/modules/Bluetooth/system/test directory.
-
-The tests are designed to be run when the Android runtime is not running. From a terminal, run:
-
-## Before you run tests
-```sh
-adb shell stop
-```
-
-## After you're done
-```sh
-adb shell start
-```
-
-## Running tests
-Then see what options the test script provides:
-
-```sh
-./run_unit_tests.sh --help
-```
-
-But for the impatient, run specific groups of tests like this:
-
-```sh
-./run_unit_tests.sh net_test_bluetooth
-```
-
-a single test:
-
-```sh
-./run_unit_tests.sh net_test_bluetooth.BluetoothTest.AdapterRepeatedEnableDisable
-```
-
-## Sample Output
-
-packages/modules/Bluetooth/system/test$ ./run_unit_tests.sh net_test_bluetooth
---- net_test_bluetooth ---
-pushing...
-/tbd/aosp-master/out/target/product/bullhead/data/nativetest/n...st_bluetooth: 1 file pushed. 9.2 MB/s (211832 bytes in 0.022s)
-running...
-
-Running main() from gtest_main.cc
-[==========] Running 11 tests from 2 test cases.
-[----------] Global test environment set-up.
-[----------] 6 tests from BluetoothTest
-[ RUN ] BluetoothTest.AdapterEnableDisable
-[ OK ] BluetoothTest.AdapterEnableDisable (2538 ms)
-[ RUN ] BluetoothTest.AdapterRepeatedEnableDisable
-[ OK ] BluetoothTest.AdapterRepeatedEnableDisable (11384 ms)
-[ RUN ] BluetoothTest.AdapterSetGetName
-[ OK ] BluetoothTest.AdapterSetGetName (2378 ms)
-[ RUN ] BluetoothTest.AdapterStartDiscovery
-[ OK ] BluetoothTest.AdapterStartDiscovery (2397 ms)
-[ RUN ] BluetoothTest.AdapterCancelDiscovery
-[ OK ] BluetoothTest.AdapterCancelDiscovery (2401 ms)
-[ RUN ] BluetoothTest.AdapterDisableDuringBonding
-[ OK ] BluetoothTest.AdapterDisableDuringBonding (11689 ms)
-[----------] 6 tests from BluetoothTest (32789 ms total)
-
-[----------] 5 tests from GattTest
-[ RUN ] GattTest.GattClientRegister
-[ OK ] GattTest.GattClientRegister (2370 ms)
-[ RUN ] GattTest.GattClientScanRemoteDevice
-[ OK ] GattTest.GattClientScanRemoteDevice (2273 ms)
-[ RUN ] GattTest.GattClientAdvertise
-[ OK ] GattTest.GattClientAdvertise (2236 ms)
-[ RUN ] GattTest.GattServerRegister
-[ OK ] GattTest.GattServerRegister (2391 ms)
-[ RUN ] GattTest.GattServerBuild
-[ OK ] GattTest.GattServerBuild (2435 ms)
-[----------] 5 tests from GattTest (11706 ms total)
-
-[----------] Global test environment tear-down
-[==========] 11 tests from 2 test cases ran. (44495 ms total)
-[ PASSED ] 11 tests.
-
-## Troubleshooting: Your phone is bricked!
-Probably not. See [After you're done](#After-you're-done)
-
diff --git a/system/test/mock/mock_bta_hearing_aid_audio_source.cc b/system/test/mock/mock_bta_hearing_aid_audio_source.cc
new file mode 100644
index 0000000000..c68fad3b8d
--- /dev/null
+++ b/system/test/mock/mock_bta_hearing_aid_audio_source.cc
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 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.
+ */
+
+/*
+ * Generated mock file from original source file
+ * Functions generated:8
+ */
+
+#include <base/functional/callback.h>
+
+#include <cstdint>
+
+#include "bta/include/bta_gatt_queue.h"
+#include "bta/include/bta_hearing_aid_api.h"
+#include "test/common/mock_functions.h"
+#include "types/raw_address.h"
+
+void HearingAidAudioSource::Start(const CodecConfiguration& /*codecConfiguration*/,
+ HearingAidAudioReceiver* /*audioReceiver*/,
+ uint16_t /*remote_delay_ms*/) {
+ inc_func_call_count(__func__);
+}
+
+void HearingAidAudioSource::Stop() { inc_func_call_count(__func__); }
+
+void HearingAidAudioSource::Initialize() { inc_func_call_count(__func__); }
+
+void HearingAidAudioSource::CleanUp() { inc_func_call_count(__func__); }
+
+void HearingAidAudioSource::DebugDump(int /*fd*/) { inc_func_call_count(__func__); }
diff --git a/system/test/mock/mock_main_shim_acl.cc b/system/test/mock/mock_main_shim_acl.cc
index a98e809ad0..5f58860347 100644
--- a/system/test/mock/mock_main_shim_acl.cc
+++ b/system/test/mock/mock_main_shim_acl.cc
@@ -129,12 +129,6 @@ void shim::Acl::DisconnectLe(uint16_t /* handle */, tHCI_STATUS /* reason */,
inc_func_call_count(__func__);
}
-void shim::Acl::LeSetDefaultSubrate(uint16_t /* subrate_min */, uint16_t /* subrate_max */,
- uint16_t /* max_latency */, uint16_t /* cont_num */,
- uint16_t /* sup_tout */) {
- inc_func_call_count(__func__);
-}
-
void shim::Acl::LeSubrateRequest(uint16_t /* hci_handle */, uint16_t /* subrate_min */,
uint16_t /* subrate_max */, uint16_t /* max_latency */,
uint16_t /* cont_num */, uint16_t /* sup_tout */) {
diff --git a/system/test/mock/mock_main_shim_acl_api.cc b/system/test/mock/mock_main_shim_acl_api.cc
index 3d257f1a5a..e3a3c9d63b 100644
--- a/system/test/mock/mock_main_shim_acl_api.cc
+++ b/system/test/mock/mock_main_shim_acl_api.cc
@@ -73,12 +73,6 @@ void bluetooth::shim::ACL_RemoveFromAddressResolution(
inc_func_call_count(__func__);
}
void bluetooth::shim::ACL_ClearAddressResolution() { inc_func_call_count(__func__); }
-void bluetooth::shim::ACL_LeSetDefaultSubrate(uint16_t /* subrate_min */,
- uint16_t /* subrate_max */,
- uint16_t /* max_latency */, uint16_t /* cont_num */,
- uint16_t /* sup_tout */) {
- inc_func_call_count(__func__);
-}
void bluetooth::shim::ACL_LeSubrateRequest(uint16_t /* hci_handle */, uint16_t /* subrate_min */,
uint16_t /* subrate_max */, uint16_t /* max_latency */,
uint16_t /* cont_num */, uint16_t /* sup_tout */) {
diff --git a/system/test/mock/mock_main_shim_acl_api.h b/system/test/mock/mock_main_shim_acl_api.h
index ab891673e3..29e27dbad3 100644
--- a/system/test/mock/mock_main_shim_acl_api.h
+++ b/system/test/mock/mock_main_shim_acl_api.h
@@ -84,21 +84,6 @@ struct ACL_ClearFilterAcceptList {
};
extern struct ACL_ClearFilterAcceptList ACL_ClearFilterAcceptList;
-// Name: ACL_LeSetDefaultSubrate
-// Params:
-// Return: void
-struct ACL_LeSetDefaultSubrate {
- std::function<void(uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency,
- uint16_t cont_num, uint16_t sup_tout)>
- body{[](uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency,
- uint16_t cont_num, uint16_t sup_tout) {}};
- void operator()(uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency,
- uint16_t cont_num, uint16_t sup_tout) {
- body(subrate_min, subrate_max, max_latency, cont_num, sup_tout);
- }
-};
-extern struct ACL_LeSetDefaultSubrate ACL_LeSetDefaultSubrate;
-
// Name: ACL_LeSubrateRequest
// Params:
// Return: void
diff --git a/system/test/mock/mock_main_shim_entry.cc b/system/test/mock/mock_main_shim_entry.cc
index 5d68f11b9d..3cdc714eaf 100644
--- a/system/test/mock/mock_main_shim_entry.cc
+++ b/system/test/mock/mock_main_shim_entry.cc
@@ -38,9 +38,9 @@ namespace bluetooth {
namespace hci {
namespace testing {
-MockAclManager* mock_acl_manager_{nullptr};
-MockControllerInterface* mock_controller_{nullptr};
-HciInterface* mock_hci_layer_{nullptr};
+std::unique_ptr<MockAclManager> mock_acl_manager_;
+std::unique_ptr<MockControllerInterface> mock_controller_;
+std::unique_ptr<MockHciLayer> mock_hci_layer_;
os::Handler* mock_gd_shim_handler_{nullptr};
MockLeAdvertisingManager* mock_le_advertising_manager_{nullptr};
MockLeScanningManager* mock_le_scanning_manager_{nullptr};
@@ -58,9 +58,9 @@ class Dumpsys;
namespace shim {
-hci::AclManager* GetAclManager() { return hci::testing::mock_acl_manager_; }
-hci::ControllerInterface* GetController() { return hci::testing::mock_controller_; }
-hci::HciInterface* GetHciLayer() { return hci::testing::mock_hci_layer_; }
+hci::AclManager* GetAclManager() { return hci::testing::mock_acl_manager_.get(); }
+hci::ControllerInterface* GetController() { return hci::testing::mock_controller_.get(); }
+hci::HciInterface* GetHciLayer() { return hci::testing::mock_hci_layer_.get(); }
hci::LeAdvertisingManager* GetAdvertising() { return hci::testing::mock_le_advertising_manager_; }
hci::LeScanningManager* GetScanning() { return hci::testing::mock_le_scanning_manager_; }
hci::DistanceMeasurementManager* GetDistanceMeasurementManager() {
diff --git a/system/test/mock/mock_main_shim_entry.h b/system/test/mock/mock_main_shim_entry.h
index ca84a27193..5d427fd963 100644
--- a/system/test/mock/mock_main_shim_entry.h
+++ b/system/test/mock/mock_main_shim_entry.h
@@ -15,11 +15,12 @@
*/
#include <functional>
+#include <memory>
#include "hci/acl_manager_mock.h"
#include "hci/controller_interface_mock.h"
#include "hci/distance_measurement_manager_mock.h"
-#include "hci/hci_interface.h"
+#include "hci/hci_layer_mock.h"
#include "hci/le_advertising_manager_mock.h"
#include "hci/le_scanning_manager_mock.h"
#include "storage/storage_module.h"
@@ -28,9 +29,9 @@ namespace bluetooth {
namespace hci {
namespace testing {
-extern MockAclManager* mock_acl_manager_;
-extern MockControllerInterface* mock_controller_;
-extern HciInterface* mock_hci_layer_;
+extern std::unique_ptr<MockAclManager> mock_acl_manager_;
+extern std::unique_ptr<MockControllerInterface> mock_controller_;
+extern std::unique_ptr<MockHciLayer> mock_hci_layer_;
extern os::Handler* mock_gd_shim_handler_;
extern MockLeAdvertisingManager* mock_le_advertising_manager_;
extern MockLeScanningManager* mock_le_scanning_manager_;
diff --git a/system/test/mock/mock_stack_gap_conn.cc b/system/test/mock/mock_stack_gap_conn_interface.cc
index 07193c9130..2ef1a3ef8f 100644
--- a/system/test/mock/mock_stack_gap_conn.cc
+++ b/system/test/mock/mock_stack_gap_conn_interface.cc
@@ -1,5 +1,5 @@
/*
- * Copyright 2021 The Android Open Source Project
+ * Copyright 2025 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.
@@ -14,19 +14,39 @@
* limitations under the License.
*/
-/*
- * Generated mock file from original source file
- * Functions generated:13
- */
+#include "test/mock/mock_stack_gap_conn_interface.h"
-#include "gap_api.h"
-#include "stack/include/bt_hdr.h"
+#include "stack/include/gap_api.h"
#include "test/common/mock_functions.h"
-#include "types/raw_address.h"
-const RawAddress* GAP_ConnGetRemoteAddr(uint16_t /* gap_handle */) {
+namespace {
+bluetooth::testing::stack::gap_conn::Mock mock_gap_conn_interface;
+bluetooth::testing::stack::gap_conn::Interface* interface_ = &mock_gap_conn_interface;
+} // namespace
+
+void bluetooth::testing::stack::gap_conn::reset_interface() {
+ interface_ = &mock_gap_conn_interface;
+}
+
+void bluetooth::testing::stack::gap_conn::set_interface(
+ bluetooth::testing::stack::gap_conn::Interface* interface) {
+ interface_ = interface;
+}
+
+uint16_t GAP_ConnOpen(const char* p_serv_name, uint8_t service_id, bool is_server,
+ const RawAddress* p_rem_bda, uint16_t psm, uint16_t le_mps,
+ tL2CAP_CFG_INFO* p_cfg, tL2CAP_ERTM_INFO* ertm_info, uint16_t security,
+ tGAP_CONN_CALLBACK* p_cb, tBT_TRANSPORT transport) {
inc_func_call_count(__func__);
- return nullptr;
+
+ return interface_->GAP_ConnOpen(p_serv_name, service_id, is_server, p_rem_bda, psm, le_mps, p_cfg,
+ ertm_info, security, p_cb, transport);
+}
+
+const RawAddress* GAP_ConnGetRemoteAddr(uint16_t gap_handle) {
+ inc_func_call_count(__func__);
+
+ return interface_->GAP_ConnGetRemoteAddr(gap_handle);
}
int GAP_GetRxQueueCnt(uint16_t /* handle */, uint32_t* /* p_rx_queue_count */) {
inc_func_call_count(__func__);
@@ -44,14 +64,6 @@ uint16_t GAP_ConnGetRemMtuSize(uint16_t /* gap_handle */) {
inc_func_call_count(__func__);
return 0;
}
-uint16_t GAP_ConnOpen(const char* /* p_serv_name */, uint8_t /* service_id */, bool /* is_server */,
- const RawAddress* /* p_rem_bda */, uint16_t /* psm */, uint16_t /* le_mps */,
- tL2CAP_CFG_INFO* /* p_cfg */, tL2CAP_ERTM_INFO* /* ertm_info */,
- uint16_t /* security */, tGAP_CONN_CALLBACK* /* p_cb */,
- tBT_TRANSPORT /* transport */) {
- inc_func_call_count(__func__);
- return 0;
-}
uint16_t GAP_ConnReadData(uint16_t /* gap_handle */, uint8_t* /* p_data */, uint16_t /* max_len */,
uint16_t* /* p_len */) {
inc_func_call_count(__func__);
@@ -74,3 +86,8 @@ bool GAP_IsTransportLe(uint16_t /* gap_handle */) {
return false;
}
void GAP_Init(void) { inc_func_call_count(__func__); }
+
+bluetooth::testing::stack::gap_conn::Interface&
+bluetooth::testing::stack::gap_conn::get_interface() {
+ return *interface_;
+}
diff --git a/system/test/mock/mock_stack_gap_conn_interface.h b/system/test/mock/mock_stack_gap_conn_interface.h
new file mode 100644
index 0000000000..c1ed7caea3
--- /dev/null
+++ b/system/test/mock/mock_stack_gap_conn_interface.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2024 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.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include <vector>
+
+#include "stack/include/gap_api.h"
+
+namespace bluetooth {
+namespace testing {
+namespace stack {
+namespace gap_conn {
+
+class Interface {
+public:
+ virtual ~Interface() = default;
+
+ virtual uint16_t GAP_ConnOpen(const char* p_serv_name, uint8_t service_id, bool is_server,
+ const RawAddress* p_rem_bda, uint16_t psm, uint16_t le_mps,
+ tL2CAP_CFG_INFO* p_cfg, tL2CAP_ERTM_INFO* ertm_info,
+ uint16_t security, tGAP_CONN_CALLBACK* p_cb,
+ tBT_TRANSPORT transport) = 0;
+
+ virtual const RawAddress* GAP_ConnGetRemoteAddr(uint16_t gap_handle) = 0;
+};
+
+class Mock : public Interface {
+public:
+ ~Mock() = default;
+
+ MOCK_METHOD(uint16_t, GAP_ConnOpen,
+ (const char* p_serv_name, uint8_t service_id, bool is_server,
+ const RawAddress* p_rem_bda, uint16_t psm, uint16_t le_mps, tL2CAP_CFG_INFO* p_cfg,
+ tL2CAP_ERTM_INFO* ertm_info, uint16_t security, tGAP_CONN_CALLBACK* p_cb,
+ tBT_TRANSPORT transport));
+
+ MOCK_METHOD(const RawAddress*, GAP_ConnGetRemoteAddr, (uint16_t gap_handle));
+};
+
+void reset_interface();
+void set_interface(Interface* interface_);
+Interface& get_interface();
+
+} // namespace gap_conn
+} // namespace stack
+} // namespace testing
+} // namespace bluetooth
diff --git a/system/test/mock/mock_stack_l2cap_interface.h b/system/test/mock/mock_stack_l2cap_interface.h
index a5cd536777..b2fc3e0ae9 100644
--- a/system/test/mock/mock_stack_l2cap_interface.h
+++ b/system/test/mock/mock_stack_l2cap_interface.h
@@ -64,9 +64,6 @@ public:
MOCK_METHOD(bool, L2CA_GetPeerFeatures,
(const RawAddress& bd_addr, uint32_t* p_ext_feat, uint8_t* p_chnl_mask));
MOCK_METHOD(bool, L2CA_SetAclPriority, (const RawAddress& bd_addr, tL2CAP_PRIORITY priority));
- MOCK_METHOD(void, L2CA_SetDefaultSubrate,
- (uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency, uint16_t cont_num,
- uint16_t timeout));
MOCK_METHOD(void, L2CA_AdjustConnectionIntervals,
(uint16_t* min_interval, uint16_t* max_interval, uint16_t floor_interval));
MOCK_METHOD(void, L2CA_SetEcosystemBaseInterval, (uint32_t base_interval));
diff --git a/system/test/mock/mock_stack_metrics_logging.cc b/system/test/mock/mock_stack_metrics_logging.cc
deleted file mode 100644
index ff2cee4472..0000000000
--- a/system/test/mock/mock_stack_metrics_logging.cc
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright 2021 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.
- */
-
-/*
- * Generated mock file from original source file
- * Functions generated:5
- *
- * mockcify.pl ver 0.2
- */
-// Mock include file to share data between tests and mock
-#include "test/mock/mock_stack_metrics_logging.h"
-
-#include <string>
-
-// Original included files, if any
-#include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
-#include <frameworks/proto_logging/stats/enums/bluetooth/hci/enums.pb.h>
-
-#include "stack/include/stack_metrics_logging.h"
-#include "test/common/mock_functions.h"
-#include "types/raw_address.h"
-
-// Mocked compile conditionals, if any
-// Mocked internal structures, if any
-
-namespace test {
-namespace mock {
-namespace stack_metrics_logging {
-
-// Function state capture and return values, if needed
-struct log_classic_pairing_event log_classic_pairing_event;
-struct log_link_layer_connection_event log_link_layer_connection_event;
-struct log_smp_pairing_event log_smp_pairing_event;
-struct log_le_pairing_fail log_le_pairing_fail;
-struct log_sdp_attribute log_sdp_attribute;
-struct log_manufacturer_info log_manufacturer_info;
-struct log_counter_metrics log_counter_metrics;
-struct log_hfp_audio_packet_loss_stats log_hfp_audio_packet_loss_stats;
-struct log_mmc_transcode_rtt_stats log_mmc_transcode_rtt_stats;
-struct log_le_connection_status log_le_connection_status;
-struct log_le_device_in_accept_list log_le_device_in_accept_list;
-struct log_le_connection_lifecycle log_le_connection_lifecycle;
-struct log_le_connection_completion log_le_connection_completion;
-
-} // namespace stack_metrics_logging
-} // namespace mock
-} // namespace test
-
-// Mocked functions, if any
-void log_classic_pairing_event(const RawAddress& address, uint16_t handle, uint32_t hci_cmd,
- uint16_t hci_event, uint16_t cmd_status, uint16_t reason_code,
- int64_t event_value) {
- inc_func_call_count(__func__);
- test::mock::stack_metrics_logging::log_classic_pairing_event(
- address, handle, hci_cmd, hci_event, cmd_status, reason_code, event_value);
-}
-void log_link_layer_connection_event(const RawAddress* address, uint32_t connection_handle,
- android::bluetooth::DirectionEnum direction,
- uint16_t link_type, uint32_t hci_cmd, uint16_t hci_event,
- uint16_t hci_ble_event, uint16_t cmd_status,
- uint16_t reason_code) {
- inc_func_call_count(__func__);
- test::mock::stack_metrics_logging::log_link_layer_connection_event(
- address, connection_handle, direction, link_type, hci_cmd, hci_event, hci_ble_event,
- cmd_status, reason_code);
-}
-void log_smp_pairing_event(const RawAddress& address, uint16_t smp_cmd,
- android::bluetooth::DirectionEnum direction, uint16_t smp_fail_reason) {
- inc_func_call_count(__func__);
- test::mock::stack_metrics_logging::log_smp_pairing_event(address, smp_cmd, direction,
- smp_fail_reason);
-}
-
-void log_le_pairing_fail(const RawAddress& raw_address, uint8_t failure_reason, bool is_outgoing) {
- inc_func_call_count(__func__);
- test::mock::stack_metrics_logging::log_le_pairing_fail(raw_address, failure_reason, is_outgoing);
-}
-
-void log_sdp_attribute(const RawAddress& address, uint16_t protocol_uuid, uint16_t attribute_id,
- size_t attribute_size, const char* attribute_value) {
- inc_func_call_count(__func__);
- test::mock::stack_metrics_logging::log_sdp_attribute(address, protocol_uuid, attribute_id,
- attribute_size, attribute_value);
-}
-void log_manufacturer_info(const RawAddress& address,
- android::bluetooth::AddressTypeEnum address_type,
- android::bluetooth::DeviceInfoSrcEnum source_type,
- const std::string& source_name, const std::string& manufacturer,
- const std::string& model, const std::string& hardware_version,
- const std::string& software_version) {
- inc_func_call_count(__func__);
- test::mock::stack_metrics_logging::log_manufacturer_info(address, address_type, source_type,
- source_name, manufacturer, model,
- hardware_version, software_version);
-}
-
-void log_counter_metrics(android::bluetooth::CodePathCounterKeyEnum key, int64_t value) {
- inc_func_call_count(__func__);
- test::mock::stack_metrics_logging::log_counter_metrics(key, value);
-}
-
-void log_hfp_audio_packet_loss_stats(const RawAddress& address, int num_decoded_frames,
- double packet_loss_ratio, uint16_t codec_type) {
- inc_func_call_count(__func__);
- test::mock::stack_metrics_logging::log_hfp_audio_packet_loss_stats(address, num_decoded_frames,
- packet_loss_ratio, codec_type);
-}
-
-void log_mmc_transcode_rtt_stats(int maximum_rtt, double mean_rtt, int num_requests,
- int codec_type) {
- inc_func_call_count(__func__);
- test::mock::stack_metrics_logging::log_mmc_transcode_rtt_stats(maximum_rtt, mean_rtt,
- num_requests, codec_type);
-}
-
-void log_le_connection_status(bluetooth::hci::Address address, bool is_connect,
- bluetooth::hci::ErrorCode reason) {
- inc_func_call_count(__func__);
- test::mock::stack_metrics_logging::log_le_connection_status(address, is_connect, reason);
-}
-
-void log_le_device_in_accept_list(bluetooth::hci::Address address, bool is_add) {
- inc_func_call_count(__func__);
- test::mock::stack_metrics_logging::log_le_device_in_accept_list(address, is_add);
-}
-
-void log_le_connection_lifecycle(bluetooth::hci::Address address, bool is_connect, bool is_direct) {
- inc_func_call_count(__func__);
- test::mock::stack_metrics_logging::log_le_connection_lifecycle(address, is_connect, is_direct);
-}
-
-void log_le_connection_completion(bluetooth::hci::Address address, bluetooth::hci::ErrorCode reason,
- bool is_locally_initiated) {
- inc_func_call_count(__func__);
- test::mock::stack_metrics_logging::log_le_connection_completion(address, reason,
- is_locally_initiated);
-}
-// END mockcify generation
diff --git a/system/test/mock/mock_stack_metrics_logging.h b/system/test/mock/mock_stack_metrics_logging.h
deleted file mode 100644
index 40212e60ea..0000000000
--- a/system/test/mock/mock_stack_metrics_logging.h
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright 2021 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.
- */
-
-/*
- * Generated mock file from original source file
- * Functions generated:5
- *
- * mockcify.pl ver 0.2
- */
-
-#include <string>
-
-// Original included files, if any
-#include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
-#include <frameworks/proto_logging/stats/enums/bluetooth/hci/enums.pb.h>
-
-#include "hci/address.h"
-#include "hci/hci_packets.h"
-#include "types/raw_address.h"
-
-// Mocked compile conditionals, if any
-
-namespace test {
-namespace mock {
-namespace stack_metrics_logging {
-
-// Shared state between mocked functions and tests
-// Name: log_classic_pairing_event
-// Params: const RawAddress& address, uint16_t handle, uint32_t hci_cmd,
-// uint16_t hci_event, uint16_t cmd_status, uint16_t reason_code, int64_t
-// event_value Returns: void
-struct log_classic_pairing_event {
- std::function<void(const RawAddress& address, uint16_t handle, uint32_t hci_cmd,
- uint16_t hci_event, uint16_t cmd_status, uint16_t reason_code,
- int64_t event_value)>
- body{[](const RawAddress& /* address */, uint16_t /* handle */, uint32_t /* hci_cmd */,
- uint16_t /* hci_event */, uint16_t /* cmd_status */, uint16_t /* reason_code */,
- int64_t /* event_value */) {}};
- void operator()(const RawAddress& address, uint16_t handle, uint32_t hci_cmd, uint16_t hci_event,
- uint16_t cmd_status, uint16_t reason_code, int64_t event_value) {
- body(address, handle, hci_cmd, hci_event, cmd_status, reason_code, event_value);
- }
-};
-extern struct log_classic_pairing_event log_classic_pairing_event;
-// Name: log_link_layer_connection_event
-// Params: const RawAddress* address, uint32_t connection_handle,
-// android::bluetooth::DirectionEnum direction, uint16_t link_type, uint32_t
-// hci_cmd, uint16_t hci_event, uint16_t hci_ble_event, uint16_t cmd_status,
-// uint16_t reason_code Returns: void
-struct log_link_layer_connection_event {
- std::function<void(const RawAddress* address, uint32_t connection_handle,
- android::bluetooth::DirectionEnum direction, uint16_t link_type,
- uint32_t hci_cmd, uint16_t hci_event, uint16_t hci_ble_event,
- uint16_t cmd_status, uint16_t reason_code)>
- body{[](const RawAddress* /* address */, uint32_t /* connection_handle */,
- android::bluetooth::DirectionEnum /* direction */, uint16_t /* link_type */,
- uint32_t /* hci_cmd */, uint16_t /* hci_event */, uint16_t /* hci_ble_event */,
- uint16_t /* cmd_status */, uint16_t /* reason_code */) {}};
- void operator()(const RawAddress* address, uint32_t connection_handle,
- android::bluetooth::DirectionEnum direction, uint16_t link_type, uint32_t hci_cmd,
- uint16_t hci_event, uint16_t hci_ble_event, uint16_t cmd_status,
- uint16_t reason_code) {
- body(address, connection_handle, direction, link_type, hci_cmd, hci_event, hci_ble_event,
- cmd_status, reason_code);
- }
-};
-extern struct log_link_layer_connection_event log_link_layer_connection_event;
-// Name: log_smp_pairing_event
-// Params: const RawAddress& address, uint16_t smp_cmd,
-// android::bluetooth::DirectionEnum direction, uint8_t smp_fail_reason Returns:
-// void
-struct log_smp_pairing_event {
- std::function<void(const RawAddress& address, uint16_t smp_cmd,
- android::bluetooth::DirectionEnum direction, uint16_t smp_fail_reason)>
- body{[](const RawAddress& /* address */, uint16_t /* smp_cmd */,
- android::bluetooth::DirectionEnum /* direction */,
- uint16_t /* smp_fail_reason */) {}};
- void operator()(const RawAddress& address, uint16_t smp_cmd,
- android::bluetooth::DirectionEnum direction, uint16_t smp_fail_reason) {
- body(address, smp_cmd, direction, smp_fail_reason);
- }
-};
-extern struct log_smp_pairing_event log_smp_pairing_event;
-
-// Name: log_le_pairing_fail
-// Params: const RawAddress& raw_address, uint8_t failure_reason, bool
-// is_outgoing Returns:
-// void
-// Name: log_sdp_attribute
-// Params: const RawAddress& address, uint16_t protocol_uuid, uint16_t
-// attribute_id, size_t attribute_size, const char* attribute_value Returns:
-// void
-struct log_le_pairing_fail {
- std::function<void(const RawAddress& raw_address, uint8_t failure_reason, bool is_outgoing)> body{
- [](const RawAddress& /* address */, uint8_t /* failure reason */,
- bool /* is_outgoing */) {}};
- void operator()(const RawAddress& raw_address, uint8_t failure_reason, bool is_outgoing) {
- body(raw_address, failure_reason, is_outgoing);
- }
-};
-extern struct log_le_pairing_fail log_le_pairing_fail;
-
-struct log_sdp_attribute {
- std::function<void(const RawAddress& address, uint16_t protocol_uuid, uint16_t attribute_id,
- size_t attribute_size, const char* attribute_value)>
- body{[](const RawAddress& /* address */, uint16_t /* protocol_uuid */,
- uint16_t /* attribute_id */, size_t /* attribute_size */,
- const char* /* attribute_value */) {}};
- void operator()(const RawAddress& address, uint16_t protocol_uuid, uint16_t attribute_id,
- size_t attribute_size, const char* attribute_value) {
- body(address, protocol_uuid, attribute_id, attribute_size, attribute_value);
- }
-};
-extern struct log_sdp_attribute log_sdp_attribute;
-// Name: log_manufacturer_info
-// Params: const RawAddress& address, android::bluetooth::DeviceInfoSrcEnum
-// source_type, const std::string& source_name, const std::string& manufacturer,
-// const std::string& model, const std::string& hardware_version, const
-// std::string& software_version Returns: void
-struct log_manufacturer_info {
- std::function<void(const RawAddress& address, android::bluetooth::AddressTypeEnum address_type,
- android::bluetooth::DeviceInfoSrcEnum source_type,
- const std::string& source_name, const std::string& manufacturer,
- const std::string& model, const std::string& hardware_version,
- const std::string& software_version)>
- body2{[](const RawAddress& /* address */,
- android::bluetooth::AddressTypeEnum /* address_type */,
- android::bluetooth::DeviceInfoSrcEnum /* source_type */,
- const std::string& /* source_name */, const std::string& /* manufacturer */,
- const std::string& /* model */, const std::string& /* hardware_version */,
- const std::string& /* software_version */) {}};
- void operator()(const RawAddress& address, android::bluetooth::AddressTypeEnum address_type,
- android::bluetooth::DeviceInfoSrcEnum source_type, const std::string& source_name,
- const std::string& manufacturer, const std::string& model,
- const std::string& hardware_version, const std::string& software_version) {
- body2(address, address_type, source_type, source_name, manufacturer, model, hardware_version,
- software_version);
- }
- std::function<void(const RawAddress& address, android::bluetooth::DeviceInfoSrcEnum source_type,
- const std::string& source_name, const std::string& manufacturer,
- const std::string& model, const std::string& hardware_version,
- const std::string& software_version)>
- body{[](const RawAddress& /* address */,
- android::bluetooth::DeviceInfoSrcEnum /* source_type */,
- const std::string& /* source_name */, const std::string& /* manufacturer */,
- const std::string& /* model */, const std::string& /* hardware_version */,
- const std::string& /* software_version */) {}};
- void operator()(const RawAddress& address, android::bluetooth::DeviceInfoSrcEnum source_type,
- const std::string& source_name, const std::string& manufacturer,
- const std::string& model, const std::string& hardware_version,
- const std::string& software_version) {
- body(address, source_type, source_name, manufacturer, model, hardware_version,
- software_version);
- }
-};
-extern struct log_manufacturer_info log_manufacturer_info;
-
-// Name: log_counter_metrics
-struct log_counter_metrics {
- std::function<void(android::bluetooth::CodePathCounterKeyEnum key, int64_t value)> body{
- [](android::bluetooth::CodePathCounterKeyEnum /* key */, int64_t /* value */) {}};
- void operator()(android::bluetooth::CodePathCounterKeyEnum key, int64_t value) {
- body(key, value);
- }
-};
-extern struct log_counter_metrics log_counter_metrics;
-
-// Name: log_hfp_audio_packet_loss_stats
-struct log_hfp_audio_packet_loss_stats {
- std::function<void(const RawAddress& address, int num_decoded_frames, double packet_loss_ratio,
- uint16_t codec_type)>
- body{[](const RawAddress& /* address */, int /* num_decoded_frames */,
- double /* packet_loss_ratio */, uint16_t /* codec_type */) {}};
- void operator()(const RawAddress& address, int num_decoded_frames, double packet_loss_ratio,
- uint16_t codec_type) {
- body(address, num_decoded_frames, packet_loss_ratio, codec_type);
- }
-};
-extern struct log_hfp_audio_packet_loss_stats log_hfp_audio_packet_loss_stats;
-
-// Name: log_mmc_transcode_rtt_stats
-struct log_mmc_transcode_rtt_stats {
- std::function<void(int maximum_rtt, double mean_rtt, int num_requests, int codec_type)> body{
- [](int /* maximum_rtt */, double /* mean_rtt */, int /* num_requests */,
- int /* codec_type */) {}};
- void operator()(int maximum_rtt, double mean_rtt, int num_requests, int codec_type) {
- body(maximum_rtt, mean_rtt, num_requests, codec_type);
- }
-};
-extern struct log_mmc_transcode_rtt_stats log_mmc_transcode_rtt_stats;
-
-// Name: log_le_connection_status
-struct log_le_connection_status {
- std::function<void(bluetooth::hci::Address address, bool is_connect,
- bluetooth::hci::ErrorCode reason)>
- body{[](bluetooth::hci::Address /* address */, bool /* is_connect */,
- bluetooth::hci::ErrorCode /* reason */) {}};
- void operator()(bluetooth::hci::Address address, bool is_connect,
- bluetooth::hci::ErrorCode reason) {
- body(address, is_connect, reason);
- }
-};
-extern struct log_le_connection_status log_le_connection_status;
-
-// Name: log_le_device_in_accept_list
-struct log_le_device_in_accept_list {
- std::function<void(bluetooth::hci::Address address, bool is_add)> body{
- [](bluetooth::hci::Address /* address */, bool /* is_add */) {}};
- void operator()(bluetooth::hci::Address address, bool is_add) { body(address, is_add); }
-};
-extern struct log_le_device_in_accept_list log_le_device_in_accept_list;
-
-// Name: log_le_connection_lifecycle
-struct log_le_connection_lifecycle {
- std::function<void(bluetooth::hci::Address address, bool is_connect, bool is_direct)> body{
- [](bluetooth::hci::Address /* address */, bool /* is_connect */, bool /* is_direct */) {
- }};
- void operator()(bluetooth::hci::Address address, bool is_connect, bool is_direct) {
- body(address, is_connect, is_direct);
- }
-};
-extern struct log_le_device_in_accept_list log_le_device_in_accept_list;
-
-// Name: log_le_connection_completion
-struct log_le_connection_completion {
- std::function<void(bluetooth::hci::Address address, bluetooth::hci::ErrorCode reason,
- bool is_locally_initiated)>
- body{[](bluetooth::hci::Address /* address */, bluetooth::hci::ErrorCode /* reason */,
- bool /* is locally initiated */) {}};
- void operator()(bluetooth::hci::Address address, bluetooth::hci::ErrorCode reason,
- bool is_locally_initiated) {
- body(address, reason, is_locally_initiated);
- }
-};
-extern struct log_le_connection_completion log_le_connection_completion;
-
-} // namespace stack_metrics_logging
-} // namespace mock
-} // namespace test
-
-// END mockcify generation
diff --git a/system/test/suite/adapter/adapter_unittest.cc b/system/test/suite/adapter/adapter_unittest.cc
index 8e2769ea10..e295cb473d 100644
--- a/system/test/suite/adapter/adapter_unittest.cc
+++ b/system/test/suite/adapter/adapter_unittest.cc
@@ -16,8 +16,11 @@
*
******************************************************************************/
+#include <bluetooth/log.h>
+
#include "adapter/bluetooth_test.h"
-#include "btcore/include/property.h"
+#include "osi/include/allocator.h"
+#include "osi/include/compat.h"
#include "types/bt_transport.h"
#include "types/raw_address.h"
@@ -58,6 +61,52 @@ TEST_F(BluetoothTest, AdapterRepeatedEnableDisable) {
}
}
+static bt_property_t* property_new_name(const char* name) {
+ bluetooth::log::assert_that(name != NULL, "assert failed: name != NULL");
+ bt_property_t* property = static_cast<bt_property_t*>(osi_calloc(sizeof(bt_property_t)));
+
+ property->val = osi_calloc(sizeof(bt_bdname_t) + 1);
+ osi_strlcpy((char*)property->val, name, sizeof(bt_bdname_t));
+
+ property->type = BT_PROPERTY_BDNAME;
+ property->len = sizeof(bt_bdname_t);
+
+ return property;
+}
+
+static void property_free(bt_property_t* property) {
+ if (property == NULL) {
+ return;
+ }
+
+ osi_free(property->val);
+ osi_free(property);
+}
+
+static const bt_bdname_t* property_as_name(const bt_property_t* property) {
+ bluetooth::log::assert_that(property->type == BT_PROPERTY_BDNAME,
+ "assert failed: property_is_name(property)");
+ return (const bt_bdname_t*)property->val;
+}
+
+static bool property_equals(const bt_property_t* p1, const bt_property_t* p2) {
+ if (!p1 || !p2 || p1->type != p2->type) {
+ return false;
+ }
+
+ if (p1->type == BT_PROPERTY_BDNAME && p1->len != p2->len) {
+ const bt_property_t *shorter = p1, *longer = p2;
+ if (p1->len > p2->len) {
+ shorter = p2;
+ longer = p1;
+ }
+ return strlen((const char*)longer->val) == (size_t)shorter->len &&
+ !memcmp(longer->val, shorter->val, shorter->len);
+ }
+
+ return p1->len == p2->len && !memcmp(p1->val, p2->val, p1->len);
+}
+
TEST_F(BluetoothTest, AdapterSetGetName) {
bt_property_t* new_name = property_new_name("BluetoothTestName1");
diff --git a/system/test/suite/adapter/bluetooth_test.cc b/system/test/suite/adapter/bluetooth_test.cc
index 4855b7a72d..490675a9f6 100644
--- a/system/test/suite/adapter/bluetooth_test.cc
+++ b/system/test/suite/adapter/bluetooth_test.cc
@@ -19,10 +19,11 @@
#include "adapter/bluetooth_test.h"
#include <binder/ProcessState.h>
+#include <bluetooth/log.h>
#include <mutex>
-#include "btcore/include/property.h"
+#include "osi/include/allocator.h"
#include "types/raw_address.h"
extern bt_interface_t bluetoothInterface;
@@ -35,6 +36,31 @@ namespace bttest {
static BluetoothTest* instance = nullptr;
+static void property_free_array(bt_property_t* properties, size_t count) {
+ if (properties == NULL) {
+ return;
+ }
+
+ for (size_t i = 0; i < count; ++i) {
+ osi_free(properties[i].val);
+ }
+
+ osi_free(properties);
+}
+
+static bt_property_t* property_copy_array(const bt_property_t* properties, size_t count) {
+ bluetooth::log::assert_that(properties != NULL, "assert failed: properties != NULL");
+ bt_property_t* clone = static_cast<bt_property_t*>(osi_calloc(sizeof(bt_property_t) * count));
+
+ memcpy(&clone[0], &properties[0], sizeof(bt_property_t) * count);
+ for (size_t i = 0; i < count; ++i) {
+ clone[i].val = osi_calloc(clone[i].len);
+ memcpy(clone[i].val, properties[i].val, clone[i].len);
+ }
+
+ return clone;
+}
+
void AdapterStateChangedCallback(bt_state_t new_state) {
instance->state_ = new_state;
semaphore_post(instance->adapter_state_changed_callback_sem_);
diff --git a/tools/OWNERS b/tools/OWNERS
deleted file mode 100644
index b2869ce1bc..0000000000
--- a/tools/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Reviewers for /tools
-
-jpawlowski@google.com
-siyuanh@google.com
-wescande@google.com
diff --git a/tools/lint/OWNERS b/tools/lint/OWNERS
deleted file mode 100644
index 9dd2d58fe3..0000000000
--- a/tools/lint/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Additional OWNERS for Bluetooth AndroidLint
-salsavage@google.com
diff --git a/tools/rootcanal/OWNERS b/tools/rootcanal/OWNERS
deleted file mode 100644
index 22b124fd96..0000000000
--- a/tools/rootcanal/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Reviewers for /tools/rootcanal
-
-henrichataing@google.com